dchelimsky-rspec 1.1.12 → 1.1.99.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/History.txt +35 -0
  2. data/License.txt +1 -1
  3. data/Manifest.txt +22 -73
  4. data/README.txt +2 -2
  5. data/Rakefile +32 -7
  6. data/TODO.txt +9 -4
  7. data/bin/spec +1 -1
  8. data/cucumber.yml +2 -0
  9. data/examples/failing/spec_helper.rb +1 -1
  10. data/examples/passing/filtered_formatter.rb +18 -0
  11. data/examples/passing/filtered_formatter_example.rb +31 -0
  12. data/examples/passing/spec_helper.rb +1 -1
  13. data/examples/ruby1.9.compatibility/access_to_constants_spec.rb +17 -18
  14. data/features/before_and_after_blocks/before_and_after_blocks.feature +4 -4
  15. data/features/example_groups/autogenerated_docstrings.feature +2 -2
  16. data/features/example_groups/example_group_with_should_methods.feature +1 -1
  17. data/features/example_groups/nested_groups.feature +1 -1
  18. data/features/interop/examples_and_tests_together.feature +1 -1
  19. data/features/interop/test_but_not_test_unit.feature +1 -1
  20. data/features/interop/test_case_with_should_methods.feature +1 -1
  21. data/features/mock_framework_integration/use_flexmock.feature +22 -4
  22. data/features/mock_framework_integration/use_mocha.feature +27 -0
  23. data/features/mock_framework_integration/use_rr.feature +27 -0
  24. data/features/step_definitions/running_rspec.rb +5 -3
  25. data/features/support/env.rb +1 -1
  26. data/features-pending/cli/conditional_exclusion.feature +39 -0
  27. data/lib/{adapters → spec/adapters}/mock_frameworks/flexmock.rb +1 -0
  28. data/lib/{adapters → spec/adapters}/mock_frameworks/mocha.rb +1 -0
  29. data/lib/{adapters → spec/adapters}/mock_frameworks/rr.rb +1 -0
  30. data/lib/{adapters → spec/adapters}/mock_frameworks/rspec.rb +0 -1
  31. data/lib/spec/autorun.rb +3 -0
  32. data/lib/spec/example/before_and_after_hooks.rb +5 -20
  33. data/lib/spec/example/example_description.rb +15 -0
  34. data/lib/spec/example/example_group.rb +0 -15
  35. data/lib/spec/example/example_group_factory.rb +34 -46
  36. data/lib/spec/example/example_group_hierarchy.rb +53 -0
  37. data/lib/spec/example/example_group_methods.rb +96 -211
  38. data/lib/spec/example/example_methods.rb +62 -81
  39. data/lib/spec/example/module_reopening_fix.rb +23 -1
  40. data/lib/spec/example/predicate_matchers.rb +47 -0
  41. data/lib/spec/example/subject.rb +91 -0
  42. data/lib/spec/example.rb +4 -0
  43. data/lib/spec/expectations/extensions.rb +0 -1
  44. data/lib/spec/expectations/handler.rb +6 -1
  45. data/lib/spec/expectations.rb +1 -1
  46. data/lib/spec/interop/test/unit/testcase.rb +5 -22
  47. data/lib/spec/interop/test.rb +1 -0
  48. data/lib/spec/matchers/be.rb +2 -7
  49. data/lib/spec/matchers/be_close.rb +20 -5
  50. data/lib/spec/matchers/change.rb +5 -3
  51. data/lib/spec/matchers/eql.rb +24 -6
  52. data/lib/spec/matchers/equal.rb +24 -6
  53. data/lib/spec/matchers/exist.rb +21 -5
  54. data/lib/spec/matchers/generated_descriptions.rb +2 -2
  55. data/lib/spec/matchers/has.rb +28 -11
  56. data/lib/spec/matchers/match.rb +25 -7
  57. data/lib/spec/matchers/match_array.rb +1 -1
  58. data/lib/spec/matchers/method_missing.rb +2 -2
  59. data/lib/spec/matchers/operator_matcher.rb +12 -5
  60. data/lib/spec/matchers/raise_error.rb +1 -1
  61. data/lib/spec/matchers/respond_to.rb +1 -1
  62. data/lib/spec/matchers/satisfy.rb +5 -5
  63. data/lib/spec/matchers/throw_symbol.rb +1 -3
  64. data/lib/spec/mocks/argument_expectation.rb +1 -1
  65. data/lib/spec/mocks/argument_matchers.rb +233 -0
  66. data/lib/spec/mocks/error_generator.rb +2 -6
  67. data/lib/spec/mocks/message_expectation.rb +3 -11
  68. data/lib/spec/mocks/mock.rb +1 -1
  69. data/lib/spec/mocks/proxy.rb +5 -1
  70. data/lib/spec/runner/configuration.rb +3 -3
  71. data/lib/spec/runner/drb_command_line.rb +2 -1
  72. data/lib/spec/runner/example_group_runner.rb +2 -1
  73. data/lib/spec/runner/formatter/base_text_formatter.rb +28 -17
  74. data/lib/spec/runner/formatter/failing_example_groups_formatter.rb +3 -5
  75. data/lib/spec/runner/formatter/html_formatter.rb +2 -3
  76. data/lib/spec/runner/formatter/nested_text_formatter.rb +7 -25
  77. data/lib/spec/runner/formatter/progress_bar_formatter.rb +1 -1
  78. data/lib/spec/runner/formatter/specdoc_formatter.rb +1 -7
  79. data/lib/spec/runner/heckle_runner_unsupported.rb +1 -1
  80. data/lib/spec/runner/option_parser.rb +16 -19
  81. data/lib/spec/runner/options.rb +28 -26
  82. data/lib/spec/runner/reporter.rb +8 -9
  83. data/lib/spec/runner.rb +6 -28
  84. data/lib/spec/test/unit.rb +10 -0
  85. data/lib/spec/version.rb +2 -2
  86. data/{features/support → resources}/helpers/cmdline.rb +2 -2
  87. data/resources/rake/verify_rcov.rake +1 -1
  88. data/resources/spec/example_group_with_should_methods.rb +1 -1
  89. data/resources/spec/simple_spec.rb +1 -1
  90. data/resources/test/spec_and_test_together.rb +2 -3
  91. data/resources/test/spec_including_test_but_not_unit.rb +1 -1
  92. data/resources/test/test_case_with_should_methods.rb +2 -3
  93. data/rspec.gemspec +5 -5
  94. data/spec/spec/dsl/main_spec.rb +3 -3
  95. data/spec/spec/example/example_group_class_definition_spec.rb +11 -14
  96. data/spec/spec/example/example_group_factory_spec.rb +31 -44
  97. data/spec/spec/example/example_group_methods_spec.rb +86 -52
  98. data/spec/spec/example/example_group_spec.rb +16 -75
  99. data/spec/spec/example/example_matcher_spec.rb +10 -10
  100. data/spec/spec/example/example_methods_spec.rb +101 -241
  101. data/spec/spec/example/nested_example_group_spec.rb +2 -2
  102. data/spec/spec/example/pending_module_spec.rb +1 -1
  103. data/spec/spec/example/shared_example_group_spec.rb +2 -2
  104. data/spec/spec/interop/test/unit/resources/spec_that_fails.rb +2 -2
  105. data/spec/spec/interop/test/unit/resources/spec_that_passes.rb +2 -2
  106. data/spec/spec/interop/test/unit/resources/spec_with_errors.rb +2 -2
  107. data/spec/spec/interop/test/unit/resources/spec_with_options_hash.rb +2 -2
  108. data/spec/spec/interop/test/unit/resources/test_case_that_fails.rb +2 -2
  109. data/spec/spec/interop/test/unit/resources/test_case_that_passes.rb +2 -2
  110. data/spec/spec/interop/test/unit/resources/test_case_with_errors.rb +2 -2
  111. data/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb +2 -2
  112. data/spec/spec/matchers/change_spec.rb +8 -0
  113. data/spec/spec/matchers/exist_spec.rb +8 -4
  114. data/spec/spec/matchers/handler_spec.rb +8 -1
  115. data/spec/spec/matchers/matcher_methods_spec.rb +1 -1
  116. data/spec/spec/mocks/{bug_report_496.rb → bug_report_496_spec.rb} +0 -0
  117. data/spec/spec/mocks/failing_argument_matchers_spec.rb +95 -0
  118. data/spec/spec/mocks/nil_expectation_warning_spec.rb +1 -1
  119. data/spec/spec/mocks/passing_argument_matchers_spec.rb +145 -0
  120. data/spec/spec/runner/configuration_spec.rb +12 -12
  121. data/spec/spec/runner/formatter/base_text_formatter_spec.rb +72 -1
  122. data/spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb +8 -8
  123. data/spec/spec/runner/formatter/failing_examples_formatter_spec.rb +4 -4
  124. data/spec/spec/runner/formatter/html_formatted-1.8.6.html +8 -8
  125. data/spec/spec/runner/formatter/html_formatted-1.8.7.html +38 -26
  126. data/spec/spec/runner/formatter/html_formatted-1.9.1.html +61 -53
  127. data/spec/spec/runner/formatter/html_formatter_spec.rb +100 -48
  128. data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +20 -34
  129. data/spec/spec/runner/formatter/profile_formatter_spec.rb +1 -1
  130. data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +8 -6
  131. data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +6 -6
  132. data/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html +20 -20
  133. data/spec/spec/runner/formatter/text_mate_formatted-1.8.7.html +38 -26
  134. data/spec/spec/runner/formatter/{spec_mate_formatter_spec.rb → text_mate_formatter_spec.rb} +10 -8
  135. data/spec/spec/runner/heckle_runner_spec.rb +1 -1
  136. data/spec/spec/runner/option_parser_spec.rb +15 -13
  137. data/spec/spec/runner/options_spec.rb +34 -0
  138. data/spec/spec/runner/reporter_spec.rb +65 -61
  139. data/spec/spec/runner/spec_drb.opts +1 -0
  140. data/spec/spec/runner_spec.rb +7 -5
  141. data/spec/spec_helper.rb +23 -0
  142. metadata +25 -76
  143. data/examples/passing/legacy_spec.rb +0 -11
  144. data/features/support/helpers/story_helper.rb +0 -13
  145. data/lib/spec/expectations/extensions/string_and_symbol.rb +0 -17
  146. data/resources/spec/spec_with_flexmock.rb +0 -19
  147. data/spec/spec/spec_spec.rb +0 -21
@@ -1,6 +1,28 @@
1
1
  module Spec
2
2
  module Example
3
- # This is a fix for ...Something in Ruby 1.8.6??... (Someone fill in here please - Aslak)
3
+ # When you reopen a module that is included in another module that is included in a class,
4
+ # the new material you define does not make it to the class. This fixes that.
5
+ #
6
+ # == Example
7
+ #
8
+ # module M1; end
9
+ #
10
+ # module M2
11
+ # def foo; "FOO"; end
12
+ # end
13
+ #
14
+ # class C
15
+ # include M1
16
+ # end
17
+ #
18
+ # module M1
19
+ # include M2
20
+ # end
21
+ #
22
+ # c = C.new
23
+ # c.foo
24
+ # NoMethodError: undefined method `foo' for #<C:0x5e89a4>
25
+ # from (irb):12
4
26
  module ModuleReopeningFix
5
27
  def child_modules
6
28
  @child_modules ||= []
@@ -0,0 +1,47 @@
1
+ module Spec
2
+ module Example
3
+ module PredicateMatchers
4
+ # :call-seq:
5
+ # predicate_matchers[matcher_name] = method_on_object
6
+ # predicate_matchers[matcher_name] = [method1_on_object, method2_on_object]
7
+ #
8
+ # Dynamically generates a custom matcher that will match
9
+ # a predicate on your class. RSpec provides a couple of these
10
+ # out of the box:
11
+ #
12
+ # exist (for state expectations)
13
+ # File.should exist("path/to/file")
14
+ #
15
+ # an_instance_of (for mock argument matchers)
16
+ # mock.should_receive(:message).with(an_instance_of(String))
17
+ #
18
+ # == Examples
19
+ #
20
+ # class Fish
21
+ # def can_swim?
22
+ # true
23
+ # end
24
+ # end
25
+ #
26
+ # describe Fish do
27
+ # predicate_matchers[:swim] = :can_swim?
28
+ # it "should swim" do
29
+ # Fish.new.should swim
30
+ # end
31
+ # end
32
+ def predicate_matchers
33
+ @predicate_matchers ||= {}
34
+ end
35
+
36
+ def define_methods_from_predicate_matchers # :nodoc:
37
+ predicate_matchers.each_pair do |matcher_method, method_on_object|
38
+ define_method matcher_method do |*args|
39
+ eval("be_#{method_on_object.to_s.gsub('?','')}(*args)")
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,91 @@
1
+ module Spec
2
+ module Example
3
+ module Subject
4
+ module ExampleGroupMethods
5
+ # Defines an explicit subject for an example group which can then be the
6
+ # implicit receiver (through delegation) of calls to +should+.
7
+ #
8
+ # == Examples
9
+ #
10
+ # describe CheckingAccount, "with $50" do
11
+ # subject { CheckingAccount.new(:amount => 50, :currency => :USD) }
12
+ # it { should have_a_balance_of(50, :USD) }
13
+ # it { should_not be_overdrawn }
14
+ # end
15
+ #
16
+ # See +ExampleMethods#should+ for more information about this approach.
17
+ def subject(&block)
18
+ if block.nil?
19
+ @_subject_block || (described_class ? lambda {described_class.new} : lambda {})
20
+ else
21
+ @_subject_block = block
22
+ end
23
+ end
24
+ end
25
+
26
+ module ExampleMethods
27
+ # Returns the subject defined in ExampleGroupMethods#subject. The
28
+ # subject block is only executed once per example, the result of which
29
+ # is cached and returned by any subsequent calls to +subject+.
30
+ #
31
+ # If a class is passed to +describe+ and no subject is explicitly
32
+ # declared in the example group, then +subject+ will return a new
33
+ # instance of that class.
34
+ #
35
+ # == Examples
36
+ #
37
+ # # explicit subject defined by the subject method
38
+ # describe Person do
39
+ # subject { Person.new(:birthdate => 19.years.ago) }
40
+ # it "should be eligible to vote" do
41
+ # subject.should be_eligible_to_vote
42
+ # end
43
+ # end
44
+ #
45
+ # # implicit subject => { Person.new }
46
+ # describe Person do
47
+ # it "should be eligible to vote" do
48
+ # subject.should be_eligible_to_vote
49
+ # end
50
+ # end
51
+ def subject
52
+ @subject ||= instance_eval(&self.class.subject)
53
+ end
54
+
55
+ # When +should+ is called with no explicit receiver, the call is
56
+ # delegated to the object returned by +subject+. Combined with
57
+ # an implicit subject (see +subject+), this supports very concise
58
+ # expressions.
59
+ #
60
+ # == Examples
61
+ #
62
+ # describe Person do
63
+ # it { should be_eligible_to_vote }
64
+ # end
65
+ def should(matcher=nil)
66
+ if matcher
67
+ subject.should(matcher)
68
+ else
69
+ subject.should
70
+ end
71
+ end
72
+
73
+ # Just like +should+, +should_not+ delegates to the subject (implicit or
74
+ # explicit) of the example group.
75
+ #
76
+ # == Examples
77
+ #
78
+ # describe Person do
79
+ # it { should_not be_eligible_to_vote }
80
+ # end
81
+ def should_not(matcher=nil)
82
+ if matcher
83
+ subject.should_not(matcher)
84
+ else
85
+ subject.should_not
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
data/lib/spec/example.rb CHANGED
@@ -173,9 +173,13 @@ module Spec
173
173
  end
174
174
 
175
175
  require 'timeout'
176
+ require 'spec/example/predicate_matchers'
177
+ require 'spec/example/example_description'
178
+ require 'spec/example/subject'
176
179
  require 'spec/example/before_and_after_hooks'
177
180
  require 'spec/example/pending'
178
181
  require 'spec/example/module_reopening_fix'
182
+ require 'spec/example/example_group_hierarchy'
179
183
  require 'spec/example/example_group_methods'
180
184
  require 'spec/example/example_methods'
181
185
  require 'spec/example/example_group'
@@ -1,2 +1 @@
1
1
  require 'spec/expectations/extensions/object'
2
- require 'spec/expectations/extensions/string_and_symbol'
@@ -22,7 +22,12 @@ module Spec
22
22
 
23
23
  return ::Spec::Matchers::NegativeOperatorMatcher.new(actual) if matcher.nil?
24
24
 
25
- match = matcher.matches?(actual, &block)
25
+ match = if matcher.respond_to?(:does_not_match?)
26
+ !matcher.does_not_match?(actual, &block)
27
+ else
28
+ matcher.matches?(actual, &block)
29
+ end
30
+
26
31
  ::Spec::Expectations.fail_with(matcher.negative_failure_message) if match
27
32
  match
28
33
  end
@@ -44,7 +44,7 @@ module Spec
44
44
  # <code>expected</code> and <code>target</code>, passes them
45
45
  # to the differ to append a diff message to the failure message.
46
46
  def self.fail_with(message, expected=nil, target=nil) # :nodoc:
47
- if Array === message && message.length == 3
47
+ if (Array === message) & (message.length == 3)
48
48
  message, expected, target = message[0], message[1], message[2]
49
49
  end
50
50
  unless (differ.nil? || expected.nil? || target.nil?)
@@ -5,8 +5,7 @@ module Test
5
5
  # This extension of the standard Test::Unit::TestCase makes RSpec
6
6
  # available from within, so that you can do things like:
7
7
  #
8
- # require 'test/unit'
9
- # require 'spec'
8
+ # require 'spec/test/unit'
10
9
  #
11
10
  # class MyTest < Test::Unit::TestCase
12
11
  # it "should work with Test::Unit assertions" do
@@ -41,33 +40,17 @@ module Test
41
40
  before(:each) {setup}
42
41
  after(:each) {teardown}
43
42
 
44
- def initialize(defined_description, options={}, &implementation)
45
- @_defined_description = defined_description
46
-
47
- # TODO - examples fail in rspec-rails if we remove "|| pending_implementation"
48
- # - find a way to fail without it in rspec's code examples
49
- @_implementation = implementation || pending_implementation
50
-
51
- @_result = ::Test::Unit::TestResult.new
52
- # @method_name is important to set here because it complies with Test::Unit's interface.
43
+ def initialize(description, options={}, &implementation)
44
+ super
53
45
  # Some Test::Unit extensions depend on @method_name being present.
54
- @method_name = @_defined_description
55
-
56
- # TODO - this is necessary to run single examples in rspec-rails, but I haven't
57
- # found a good way to write a failing example just within rspec core
58
- @_backtrace = caller
46
+ @method_name = description
47
+ @_result = ::Test::Unit::TestResult.new
59
48
  end
60
49
 
61
50
  def run(ignore_this_argument=nil)
62
51
  super()
63
52
  end
64
53
 
65
- private
66
-
67
- def pending_implementation
68
- error = Spec::Example::NotYetImplementedError.new(caller)
69
- lambda { raise(error) }
70
- end
71
54
  end
72
55
  end
73
56
  end
@@ -1,3 +1,4 @@
1
+ require 'spec'
1
2
  require 'test/unit'
2
3
  require 'test/unit/testresult'
3
4
 
@@ -60,12 +60,7 @@ it reads really poorly.
60
60
 
61
61
  private
62
62
  def match_or_compare(actual)
63
- case @expected
64
- when TrueClass
65
- @actual
66
- else
67
- @actual.__send__(comparison_method, @expected)
68
- end
63
+ TrueClass === @expected ? @actual : @actual.__send__(comparison_method, @expected)
69
64
  end
70
65
 
71
66
  def comparison_method
@@ -87,7 +82,7 @@ it reads really poorly.
87
82
  def parse_expected(expected)
88
83
  ["be_an_","be_a_","be_"].each do |prefix|
89
84
  handling_predicate!
90
- if expected.starts_with?(prefix)
85
+ if expected.to_s =~ /^#{prefix}/
91
86
  set_prefix(prefix)
92
87
  expected = expected.to_s.sub(prefix,"")
93
88
  [true, false, nil].each do |val|
@@ -1,5 +1,24 @@
1
1
  module Spec
2
2
  module Matchers
3
+
4
+ class BeClose
5
+ def initialize(expected, delta)
6
+ @expected, @delta = expected, delta
7
+ end
8
+
9
+ def matches?(actual)
10
+ @actual = actual
11
+ (@actual - @expected).abs < @delta
12
+ end
13
+
14
+ def failure_message
15
+ "expected #{@expected} +/- (< #{@delta}), got #{@actual}"
16
+ end
17
+
18
+ def description
19
+ "be close to #{@expected} (within +- #{@delta})"
20
+ end
21
+ end
3
22
 
4
23
  # :call-seq:
5
24
  # should be_close(expected, delta)
@@ -11,11 +30,7 @@ module Spec
11
30
  #
12
31
  # result.should be_close(3.0, 0.5)
13
32
  def be_close(expected, delta)
14
- simple_matcher do |actual, matcher|
15
- matcher.failure_message = "expected #{expected} +/- (< #{delta}), got #{actual}"
16
- matcher.description = "be close to #{expected} (within +- #{delta})"
17
- (actual - expected).abs < delta
18
- end
33
+ BeClose.new(expected, delta)
19
34
  end
20
35
  end
21
36
  end
@@ -5,9 +5,7 @@ module Spec
5
5
  class Change #:nodoc:
6
6
  def initialize(receiver=nil, message=nil, &block)
7
7
  @message = message || "result"
8
- @value_proc = block || lambda {
9
- receiver.__send__(message)
10
- }
8
+ @value_proc = block || lambda {receiver.__send__(message)}
11
9
  end
12
10
 
13
11
  def matches?(event_proc)
@@ -84,6 +82,10 @@ MESSAGE
84
82
  @from = from
85
83
  self
86
84
  end
85
+
86
+ def description
87
+ "change ##{@message}"
88
+ end
87
89
  end
88
90
 
89
91
  # :call-seq:
@@ -1,5 +1,28 @@
1
1
  module Spec
2
2
  module Matchers
3
+ class Eql
4
+ def initialize(expected)
5
+ @expected = expected
6
+ end
7
+
8
+ def matches?(actual)
9
+ @actual = actual
10
+ @actual.eql?(@expected)
11
+ end
12
+
13
+ def failure_message
14
+ return "expected #{@expected.inspect}, got #{@actual.inspect} (using .eql?)", @expected, @actual
15
+ end
16
+
17
+ def negative_failure_message
18
+ return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .eql?)", @expected, @actual
19
+ end
20
+
21
+ def description
22
+ "eql #{@expected.inspect}"
23
+ end
24
+ end
25
+
3
26
 
4
27
  # :call-seq:
5
28
  # should eql(expected)
@@ -14,12 +37,7 @@ module Spec
14
37
  # 5.should eql(5)
15
38
  # 5.should_not eql(3)
16
39
  def eql(expected)
17
- simple_matcher do |actual, matcher|
18
- matcher.failure_message = "expected #{expected.inspect}, got #{actual.inspect} (using .eql?)", expected, actual
19
- matcher.negative_failure_message = "expected #{actual.inspect} not to equal #{expected.inspect} (using .eql?)", expected, actual
20
- matcher.description = "eql #{expected.inspect}"
21
- actual.eql?(expected)
22
- end
40
+ Eql.new(expected)
23
41
  end
24
42
  end
25
43
  end
@@ -1,5 +1,28 @@
1
1
  module Spec
2
2
  module Matchers
3
+
4
+ class Equal
5
+ def initialize(expected)
6
+ @expected = expected
7
+ end
8
+
9
+ def matches?(actual)
10
+ @actual = actual
11
+ @actual.equal?(@expected)
12
+ end
13
+
14
+ def failure_message
15
+ return "expected #{@expected.inspect}, got #{@actual.inspect} (using .equal?)", @expected, @actual
16
+ end
17
+
18
+ def negative_failure_message
19
+ return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .equal?)", @expected, @actual
20
+ end
21
+
22
+ def description
23
+ "equal #{@expected.inspect}"
24
+ end
25
+ end
3
26
 
4
27
  # :call-seq:
5
28
  # should equal(expected)
@@ -14,12 +37,7 @@ module Spec
14
37
  # 5.should equal(5) #Fixnums are equal
15
38
  # "5".should_not equal("5") #Strings that look the same are not the same object
16
39
  def equal(expected)
17
- simple_matcher do |actual, matcher|
18
- matcher.failure_message = "expected #{expected.inspect}, got #{actual.inspect} (using .equal?)", expected, actual
19
- matcher.negative_failure_message = "expected #{actual.inspect} not to equal #{expected.inspect} (using .equal?)", expected, actual
20
- matcher.description = "equal #{expected.inspect}"
21
- actual.equal?(expected)
22
- end
40
+ Equal.new(expected)
23
41
  end
24
42
  end
25
43
  end
@@ -1,16 +1,32 @@
1
1
  module Spec
2
2
  module Matchers
3
+
4
+ class Exist
5
+ def matches?(actual)
6
+ @actual = actual
7
+ actual.exist?
8
+ end
9
+
10
+ def failure_message
11
+ "expected #{@actual.inspect} to exist, but it doesn't."
12
+ end
13
+
14
+ def negative_failure_message
15
+ "expected #{@actual.inspect} to not exist, but it does."
16
+ end
17
+
18
+ def description
19
+ "exists"
20
+ end
21
+ end
22
+
3
23
  # :call-seq:
4
24
  # should exist
5
25
  # should_not exist
6
26
  #
7
27
  # Passes if actual.exist?
8
28
  def exist
9
- simple_matcher do |actual, matcher|
10
- matcher.failure_message = "expected #{actual.inspect} to exist, but it doesn't."
11
- matcher.negative_failure_message = "expected #{actual.inspect} to not exist, but it does."
12
- actual.exist?
13
- end
29
+ Exist.new
14
30
  end
15
31
  end
16
32
  end
@@ -38,11 +38,11 @@ or this:
38
38
 
39
39
  it { should matcher }
40
40
 
41
- the runner expects the matcher to have a #describe method. You should either
41
+ the runner expects the matcher to have a #description method. You should either
42
42
  add a String to the example this matcher is being used in, or give it a
43
43
  description method. Then you won't have to suffer this lengthy warning again.
44
44
  MESSAGE
45
45
  end
46
46
  end
47
47
  end
48
-
48
+
@@ -1,18 +1,35 @@
1
1
  module Spec
2
2
  module Matchers
3
- def has(sym, *args) # :nodoc:
4
- simple_matcher do |actual, matcher|
5
- matcher.failure_message = "expected ##{predicate(sym)}(#{args[0].inspect}) to return true, got false"
6
- matcher.negative_failure_message = "expected ##{predicate(sym)}(#{args[0].inspect}) to return false, got true"
7
- matcher.description = "have key #{args[0].inspect}"
8
- actual.__send__(predicate(sym), *args)
3
+
4
+ class Has
5
+
6
+ def initialize(expected, *args)
7
+ @expected, @args = expected, args
9
8
  end
10
- end
9
+
10
+ def matches?(actual)
11
+ actual.__send__(predicate(@expected), *@args)
12
+ end
13
+
14
+ def failure_message
15
+ "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return true, got false"
16
+ end
17
+
18
+ def negative_failure_message
19
+ "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return false, got true"
20
+ end
21
+
22
+ def description
23
+ "have key #{@args[0].inspect}"
24
+ end
25
+
26
+ private
11
27
 
12
- private
13
- def predicate(sym)
14
- "#{sym.to_s.sub("have_","has_")}?".to_sym
28
+ def predicate(sym)
29
+ "#{sym.to_s.sub("have_","has_")}?".to_sym
30
+ end
31
+
15
32
  end
16
-
33
+
17
34
  end
18
35
  end
@@ -1,5 +1,28 @@
1
1
  module Spec
2
2
  module Matchers
3
+ class Match
4
+ def initialize(expected)
5
+ @expected = expected
6
+ end
7
+
8
+ def matches?(actual)
9
+ @actual = actual
10
+ actual =~ @expected
11
+ end
12
+
13
+ def failure_message
14
+ return "expected #{@actual.inspect} to match #{@expected.inspect}", @expected, @actual
15
+ end
16
+
17
+ def negative_failure_message
18
+ return "expected #{@actual.inspect} not to match #{@expected.inspect}", @expected, @actual
19
+ end
20
+
21
+ def description
22
+ "match #{@expected.inspect}"
23
+ end
24
+ end
25
+
3
26
 
4
27
  # :call-seq:
5
28
  # should match(regexp)
@@ -10,13 +33,8 @@ module Spec
10
33
  # == Examples
11
34
  #
12
35
  # email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
13
- def match(regexp)
14
- simple_matcher do |actual, matcher|
15
- matcher.failure_message = "expected #{actual.inspect} to match #{regexp.inspect}", regexp, actual
16
- matcher.negative_failure_message = "expected #{actual.inspect} not to match #{regexp.inspect}", regexp, actual
17
- matcher.description = "match #{regexp.inspect}"
18
- actual =~ regexp
19
- end
36
+ def match(expected)
37
+ Match.new(expected)
20
38
  end
21
39
  end
22
40
  end
@@ -11,7 +11,7 @@ module Spec
11
11
  @actual = actual
12
12
  @extra_items = difference_between_arrays(@actual, @expected)
13
13
  @missing_items = difference_between_arrays(@expected, @actual)
14
- @extra_items.empty? && @missing_items.empty?
14
+ @extra_items.empty? & @missing_items.empty?
15
15
  end
16
16
 
17
17
  def failure_message
@@ -1,8 +1,8 @@
1
1
  module Spec
2
2
  module Matchers
3
3
  def method_missing(sym, *args, &block) # :nodoc:
4
- return Matchers::Be.new(sym, *args) if sym.starts_with?("be_")
5
- return has(sym, *args) if sym.starts_with?("have_")
4
+ return Matchers::Be.new(sym, *args) if sym.to_s =~ /^be_/
5
+ return Matchers::Has.new(sym, *args) if sym.to_s =~ /^have_/
6
6
  super
7
7
  end
8
8
  end
@@ -4,15 +4,16 @@ module Spec
4
4
  class OperatorMatcher
5
5
  class << self
6
6
  def registry
7
- @registry ||= Hash.new {|h,k| h[k] = {}}
7
+ @registry ||= {}
8
8
  end
9
9
 
10
10
  def register(klass, operator, matcher)
11
+ registry[klass] ||= {}
11
12
  registry[klass][operator] = matcher
12
13
  end
13
14
 
14
15
  def get(klass, operator)
15
- registry[klass][operator]
16
+ registry[klass] && registry[klass][operator]
16
17
  end
17
18
  end
18
19
 
@@ -25,9 +26,7 @@ module Spec
25
26
  if matcher = OperatorMatcher.get(@actual.class, operator)
26
27
  @actual.send(::Spec::Matchers.last_should, matcher.new(expected))
27
28
  else
28
- ::Spec::Matchers.last_matcher = self
29
- @operator, @expected = operator, expected
30
- __delegate_operator(@actual, operator, expected)
29
+ eval_match(@actual, operator, expected)
31
30
  end
32
31
  end
33
32
  end
@@ -43,6 +42,14 @@ module Spec
43
42
  def description
44
43
  "#{@operator} #{@expected.inspect}"
45
44
  end
45
+
46
+ private
47
+
48
+ def eval_match(actual, operator, expected)
49
+ ::Spec::Matchers.last_matcher = self
50
+ @operator, @expected = operator, expected
51
+ __delegate_operator(actual, operator, expected)
52
+ end
46
53
 
47
54
  end
48
55
 
@@ -31,7 +31,7 @@ module Spec
31
31
  eval_block if @raised_expected_error && @with_expected_message && @block
32
32
  end
33
33
  ensure
34
- return (@raised_expected_error && @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
34
+ return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
35
35
  end
36
36
 
37
37
  def eval_block
@@ -25,7 +25,6 @@ module Spec
25
25
  end
26
26
 
27
27
  def description
28
- # Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here
29
28
  "respond to #{pp_names}#{with_arity}"
30
29
  end
31
30
 
@@ -51,6 +50,7 @@ module Spec
51
50
  end
52
51
 
53
52
  def pp_names
53
+ # Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here
54
54
  @names.length == 1 ? "##{@names.first}" : @names.inspect
55
55
  end
56
56
  end