rspec 1.2.9 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/History.rdoc +51 -1
  2. data/License.txt +1 -1
  3. data/Manifest.txt +11 -4
  4. data/README.rdoc +10 -24
  5. data/Rakefile +17 -13
  6. data/Upgrade.rdoc +63 -2
  7. data/examples/passing/shared_example_group_example.rb +0 -36
  8. data/examples/passing/simple_matcher_example.rb +3 -3
  9. data/features/formatters/nested_formatter.feature +32 -0
  10. data/features/interop/cucumber_stubs_dont_leak.feature +11 -0
  11. data/features/interop/test_but_not_test_unit.feature +1 -1
  12. data/features/interop/test_case_with_should_methods.feature +1 -1
  13. data/features/matchers/define_matcher_with_fluent_interface.feature +21 -0
  14. data/features/matchers/define_wrapped_matcher.feature +28 -1
  15. data/features/matchers/match_unless_raises.feature +60 -0
  16. data/features/matchers/match_unless_raises_unexpected_error.feature +39 -0
  17. data/features/mocks/block_local_expectations.feature +62 -0
  18. data/features/step_definitions/running_rspec_steps.rb +9 -0
  19. data/features/step_definitions/stubbing_steps.rb +16 -0
  20. data/features/support/env.rb +1 -0
  21. data/features/support/matchers/smart_match.rb +23 -4
  22. data/geminstaller.yml +29 -0
  23. data/lib/autotest/rspec.rb +14 -7
  24. data/lib/spec/deprecation.rb +2 -1
  25. data/lib/spec/dsl/main.rb +2 -1
  26. data/lib/spec/example/example_group_methods.rb +6 -1
  27. data/lib/spec/example/example_methods.rb +4 -0
  28. data/lib/spec/example/subject.rb +9 -3
  29. data/lib/spec/interop/test/unit/testsuite_adapter.rb +2 -0
  30. data/lib/spec/interop/test.rb +1 -1
  31. data/lib/spec/matchers/be.rb +167 -128
  32. data/lib/spec/matchers/has.rb +3 -3
  33. data/lib/spec/matchers/have.rb +1 -0
  34. data/lib/spec/matchers/matcher.rb +55 -10
  35. data/lib/spec/matchers/method_missing.rb +2 -2
  36. data/lib/spec/matchers/operator_matcher.rb +6 -1
  37. data/lib/spec/matchers/pretty.rb +2 -2
  38. data/lib/spec/matchers/raise_exception.rb +131 -0
  39. data/lib/spec/matchers/simple_matcher.rb +2 -1
  40. data/lib/spec/matchers/throw_symbol.rb +18 -22
  41. data/lib/spec/matchers.rb +21 -2
  42. data/lib/spec/mocks/message_expectation.rb +63 -48
  43. data/lib/spec/mocks/methods.rb +13 -8
  44. data/lib/spec/mocks/proxy.rb +45 -22
  45. data/lib/spec/runner/backtrace_tweaker.rb +3 -2
  46. data/lib/spec/runner/configuration.rb +8 -0
  47. data/lib/spec/runner/differs/default.rb +1 -1
  48. data/lib/spec/runner/drb_command_line.rb +8 -2
  49. data/lib/spec/runner/example_group_runner.rb +1 -2
  50. data/lib/spec/runner/formatter/nested_text_formatter.rb +6 -3
  51. data/lib/spec/runner/option_parser.rb +2 -0
  52. data/lib/spec/runner/options.rb +8 -2
  53. data/lib/spec/stubs/cucumber.rb +2 -2
  54. data/lib/spec/version.rb +2 -2
  55. data/spec/autotest/autotest_helper.rb +1 -1
  56. data/spec/autotest/discover_spec.rb +2 -2
  57. data/spec/autotest/failed_results_re_spec.rb +2 -2
  58. data/spec/autotest/rspec_spec.rb +21 -6
  59. data/spec/spec/dsl/main_spec.rb +10 -2
  60. data/spec/spec/example/example_group_methods_spec.rb +21 -1
  61. data/spec/spec/example/example_group_proxy_spec.rb +1 -1
  62. data/spec/spec/example/example_group_spec.rb +1 -12
  63. data/spec/spec/example/example_matcher_spec.rb +3 -4
  64. data/spec/spec/example/subject_spec.rb +7 -0
  65. data/spec/spec/expectations/wrap_expectation_spec.rb +2 -1
  66. data/spec/spec/interop/test/unit/spec_spec.rb +7 -7
  67. data/spec/spec/interop/test/unit/testcase_spec.rb +7 -7
  68. data/spec/spec/interop/test/unit/testsuite_adapter_spec.rb +1 -1
  69. data/spec/spec/matchers/be_spec.rb +159 -10
  70. data/spec/spec/matchers/has_spec.rb +109 -0
  71. data/spec/spec/matchers/have_spec.rb +278 -293
  72. data/spec/spec/matchers/match_array_spec.rb +8 -1
  73. data/spec/spec/matchers/matcher_spec.rb +70 -9
  74. data/spec/spec/matchers/raise_exception_spec.rb +345 -0
  75. data/spec/spec/matchers/simple_matcher_spec.rb +51 -44
  76. data/spec/spec/matchers/throw_symbol_spec.rb +83 -58
  77. data/spec/spec/mocks/and_yield_spec.rb +117 -0
  78. data/spec/spec/mocks/bug_report_496_spec.rb +2 -4
  79. data/spec/spec/mocks/mock_spec.rb +2 -2
  80. data/spec/spec/runner/command_line_spec.rb +26 -5
  81. data/spec/spec/runner/drb_command_line_spec.rb +39 -0
  82. data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +35 -11
  83. data/spec/spec/runner/option_parser_spec.rb +12 -6
  84. data/spec/spec/runner/options_spec.rb +7 -0
  85. data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +23 -5
  86. data/spec/spec_helper.rb +2 -1
  87. metadata +107 -38
  88. data/lib/spec/matchers/raise_error.rb +0 -129
  89. data/spec/spec/matchers/matcher_methods_spec.rb +0 -63
  90. data/spec/spec/matchers/raise_error_spec.rb +0 -333
  91. /data/lib/spec/{matchers/extensions → extensions}/instance_exec.rb +0 -0
@@ -5,6 +5,7 @@ module Spec
5
5
  @expected = (expected == :no ? 0 : expected)
6
6
  @relativity = relativity
7
7
  @actual = nil
8
+ @plural_collection_name = nil
8
9
  end
9
10
 
10
11
  def relativities
@@ -12,6 +12,7 @@ module Spec
12
12
  @expected = expected
13
13
  @actual = nil
14
14
  @diffable = false
15
+ @expected_exception = nil
15
16
  @messages = {
16
17
  :description => lambda {"#{name_to_sentence}#{expected_to_sentence}"},
17
18
  :failure_message_for_should => lambda {|actual| "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"},
@@ -22,33 +23,70 @@ module Spec
22
23
  end
23
24
  end
24
25
 
26
+ #Used internally by objects returns by +should+ and +should_not+.
25
27
  def matches?(actual)
26
- instance_exec(@actual = actual, &@match_block)
28
+ @actual = actual
29
+ if @expected_exception
30
+ begin
31
+ instance_exec(actual, &@match_block)
32
+ true
33
+ rescue @expected_exception
34
+ false
35
+ end
36
+ else
37
+ begin
38
+ instance_exec(actual, &@match_block)
39
+ rescue Spec::Expectations::ExpectationNotMetError
40
+ false
41
+ end
42
+ end
27
43
  end
28
44
 
29
- def description(&block)
30
- cache_or_call_cached(:description, &block)
45
+ # See Spec::Matchers
46
+ def match(&block)
47
+ @match_block = block
31
48
  end
32
49
 
50
+ # See Spec::Matchers
51
+ def match_unless_raises(exception=Exception, &block)
52
+ @expected_exception = exception
53
+ match(&block)
54
+ end
55
+
56
+ # See Spec::Matchers
33
57
  def failure_message_for_should(&block)
34
- cache_or_call_cached(:failure_message_for_should, actual, &block)
58
+ cache_or_call_cached(:failure_message_for_should, &block)
35
59
  end
36
60
 
61
+ # See Spec::Matchers
37
62
  def failure_message_for_should_not(&block)
38
- cache_or_call_cached(:failure_message_for_should_not, actual, &block)
63
+ cache_or_call_cached(:failure_message_for_should_not, &block)
39
64
  end
40
65
 
41
- def match(&block)
42
- @match_block = block
66
+ # See Spec::Matchers
67
+ def description(&block)
68
+ cache_or_call_cached(:description, &block)
43
69
  end
44
70
 
71
+ #Used internally by objects returns by +should+ and +should_not+.
45
72
  def diffable?
46
73
  @diffable
47
74
  end
48
75
 
76
+ # See Spec::Matchers
49
77
  def diffable
50
78
  @diffable = true
51
79
  end
80
+
81
+ # See Spec::Matchers
82
+ def chain(method, &block)
83
+ self.class.class_eval do
84
+ define_method method do |*args|
85
+ block.call(*args)
86
+ self
87
+ end
88
+ end
89
+ end
52
90
 
53
91
  private
54
92
 
@@ -69,9 +107,16 @@ module Spec
69
107
  (private_methods - orig_private_methods).each {|m| st.__send__ :public, m}
70
108
  end
71
109
 
72
- def cache_or_call_cached(key, actual=nil, &block)
73
- block ? @messages[key] = block :
74
- actual.nil? ? @messages[key].call : @messages[key].call(actual)
110
+ def cache_or_call_cached(key, &block)
111
+ block ? cache(key, &block) : call_cached(key)
112
+ end
113
+
114
+ def cache(key, &block)
115
+ @messages[key] = block
116
+ end
117
+
118
+ def call_cached(key)
119
+ @messages[key].arity == 1 ? @messages[key].call(@actual) : @messages[key].call
75
120
  end
76
121
 
77
122
  def name_to_sentence
@@ -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.to_s =~ /^be_/
5
- return Matchers::Has.new(sym, *args) if sym.to_s =~ /^have_/
4
+ return Matchers::BePredicate.new(sym, *args, &block) if sym.to_s =~ /^be_/
5
+ return Matchers::Has.new(sym, *args, &block) if sym.to_s =~ /^have_/
6
6
  super
7
7
  end
8
8
  end
@@ -13,7 +13,12 @@ module Spec
13
13
  end
14
14
 
15
15
  def get(klass, operator)
16
- registry[klass] && registry[klass][operator]
16
+ matcher = registry[klass] && registry[klass][operator]
17
+ unless matcher
18
+ parent_class = registry.keys.detect {|pc| klass <= pc }
19
+ matcher = registry[parent_class] && registry[parent_class][operator]
20
+ end
21
+ matcher
17
22
  end
18
23
  end
19
24
 
@@ -5,7 +5,7 @@ module Spec
5
5
  sym.to_s.gsub(/_/,' ')
6
6
  end
7
7
 
8
- def to_sentence(words)
8
+ def to_sentence(words=[])
9
9
  words = words.map{|w| w.inspect}
10
10
  case words.length
11
11
  when 0
@@ -34,4 +34,4 @@ module Spec
34
34
  end
35
35
  end
36
36
  end
37
- end
37
+ end
@@ -0,0 +1,131 @@
1
+ module Spec
2
+ module Matchers
3
+ class RaiseException #:nodoc:
4
+ def initialize(expected_exception_or_message=Exception, expected_message=nil, &block)
5
+ @block = block
6
+ @actual_exception = nil
7
+ case expected_exception_or_message
8
+ when String, Regexp
9
+ @expected_exception, @expected_message = Exception, expected_exception_or_message
10
+ else
11
+ @expected_exception, @expected_message = expected_exception_or_message, expected_message
12
+ end
13
+ end
14
+
15
+ def matches?(given_proc)
16
+ @raised_expected_exception = false
17
+ @with_expected_message = false
18
+ @eval_block = false
19
+ @eval_block_passed = false
20
+ begin
21
+ given_proc.call
22
+ rescue @expected_exception => @actual_exception
23
+ @raised_expected_exception = true
24
+ @with_expected_message = verify_message
25
+ rescue Exception => @actual_exception
26
+ # This clause should be empty, but rcov will not report it as covered
27
+ # unless something (anything) is executed within the clause
28
+ rcov_exception_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
29
+ end
30
+
31
+ unless negative_expectation?
32
+ eval_block if @raised_expected_exception && @with_expected_message && @block
33
+ end
34
+
35
+ (@raised_expected_exception & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
36
+ end
37
+
38
+ def eval_block
39
+ @eval_block = true
40
+ begin
41
+ @block[@actual_exception]
42
+ @eval_block_passed = true
43
+ rescue Exception => err
44
+ @actual_exception = err
45
+ end
46
+ end
47
+
48
+ def verify_message
49
+ case @expected_message
50
+ when nil
51
+ true
52
+ when Regexp
53
+ @expected_message =~ @actual_exception.message
54
+ else
55
+ @expected_message == @actual_exception.message
56
+ end
57
+ end
58
+
59
+ def failure_message_for_should
60
+ @eval_block ? @actual_exception.message : "expected #{expected_exception}#{given_exception}"
61
+ end
62
+
63
+ def failure_message_for_should_not
64
+ "expected no #{expected_exception}#{given_exception}"
65
+ end
66
+
67
+ def description
68
+ "raise #{expected_exception}"
69
+ end
70
+
71
+ private
72
+ def expected_exception
73
+ case @expected_message
74
+ when nil
75
+ @expected_exception
76
+ when Regexp
77
+ "#{@expected_exception} with message matching #{@expected_message.inspect}"
78
+ else
79
+ "#{@expected_exception} with #{@expected_message.inspect}"
80
+ end
81
+ end
82
+
83
+ def given_exception
84
+ @actual_exception.nil? ? " but nothing was raised" : ", got #{@actual_exception.inspect}"
85
+ end
86
+
87
+ def negative_expectation?
88
+ # YES - I'm a bad person... help me find a better way - ryand
89
+ caller.first(3).find { |s| s =~ /should_not/ }
90
+ end
91
+ end
92
+
93
+ # :call-seq:
94
+ # should raise_exception()
95
+ # should raise_exception(NamedError)
96
+ # should raise_exception(NamedError, String)
97
+ # should raise_exception(NamedError, Regexp)
98
+ # should raise_exception() { |exception| ... }
99
+ # should raise_exception(NamedError) { |exception| ... }
100
+ # should raise_exception(NamedError, String) { |exception| ... }
101
+ # should raise_exception(NamedError, Regexp) { |exception| ... }
102
+ # should_not raise_exception()
103
+ # should_not raise_exception(NamedError)
104
+ # should_not raise_exception(NamedError, String)
105
+ # should_not raise_exception(NamedError, Regexp)
106
+ #
107
+ # With no args, matches if any exception is raised.
108
+ # With a named exception, matches only if that specific exception is raised.
109
+ # With a named exception and messsage specified as a String, matches only if both match.
110
+ # With a named exception and messsage specified as a Regexp, matches only if both match.
111
+ # Pass an optional block to perform extra verifications on the exception matched
112
+ #
113
+ # == Examples
114
+ #
115
+ # lambda { do_something_risky }.should raise_exception
116
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError)
117
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError) { |exception| exception.data.should == 42 }
118
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError, "that was too risky")
119
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError, /oo ri/)
120
+ #
121
+ # lambda { do_something_risky }.should_not raise_exception
122
+ # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError)
123
+ # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError, "that was too risky")
124
+ # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError, /oo ri/)
125
+ def raise_exception(exception=Exception, message=nil, &block)
126
+ Matchers::RaiseException.new(exception, message, &block)
127
+ end
128
+
129
+ alias_method :raise_error, :raise_exception
130
+ end
131
+ end
@@ -127,7 +127,8 @@ module Spec
127
127
  # failing), will fail when you want it to pass.
128
128
  #
129
129
  def simple_matcher(description=nil, &match_block)
130
+ Spec.deprecate("simple_matcher", "Matcher DSL (http://rspec.rubyforge.org/rspec/1.3.0/classes/Spec/Matchers.html)")
130
131
  SimpleMatcher.new(description, &match_block)
131
132
  end
132
133
  end
133
- end
134
+ end
@@ -1,13 +1,13 @@
1
1
  module Spec
2
2
  module Matchers
3
-
3
+
4
4
  class ThrowSymbol #:nodoc:
5
5
  def initialize(expected_symbol = nil, expected_arg=nil)
6
6
  @expected_symbol = expected_symbol
7
7
  @expected_arg = expected_arg
8
8
  @caught_symbol = @caught_arg = nil
9
9
  end
10
-
10
+
11
11
  def matches?(given_proc)
12
12
  begin
13
13
  if @expected_symbol.nil?
@@ -27,17 +27,13 @@ module Spec
27
27
  rescue NameError, ArgumentError => e
28
28
  raise e unless e.message =~ /uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/
29
29
  @caught_symbol = $2.to_sym
30
-
31
- ensure
32
- if @expected_symbol.nil?
33
- return !@caught_symbol.nil?
34
- else
35
- if @expected_arg.nil?
36
- return @caught_symbol == @expected_symbol
37
- else
38
- return (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg)
39
- end
40
- end
30
+ end
31
+ if @expected_symbol.nil?
32
+ !@caught_symbol.nil?
33
+ elsif @expected_arg.nil?
34
+ @caught_symbol == @expected_symbol
35
+ else
36
+ (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg)
41
37
  end
42
38
  end
43
39
 
@@ -48,7 +44,7 @@ module Spec
48
44
  "expected #{expected} but nothing was thrown"
49
45
  end
50
46
  end
51
-
47
+
52
48
  def failure_message_for_should_not
53
49
  if @expected_symbol
54
50
  "expected #{expected} not to be thrown"
@@ -56,23 +52,23 @@ module Spec
56
52
  "expected no Symbol, got :#{@caught_symbol}"
57
53
  end
58
54
  end
59
-
55
+
60
56
  def description
61
57
  "throw #{expected}"
62
58
  end
63
-
59
+
64
60
  private
65
-
61
+
66
62
  def expected
67
63
  @expected_symbol.nil? ? "a Symbol" : "#{@expected_symbol.inspect}#{args}"
68
64
  end
69
-
65
+
70
66
  def args
71
67
  @expected_arg.nil? ? "" : " with #{@expected_arg.inspect}"
72
68
  end
73
-
69
+
74
70
  end
75
-
71
+
76
72
  # :call-seq:
77
73
  # should throw_symbol()
78
74
  # should throw_symbol(:sym)
@@ -97,8 +93,8 @@ module Spec
97
93
  # lambda { do_something_risky }.should_not throw_symbol
98
94
  # lambda { do_something_risky }.should_not throw_symbol(:that_was_risky)
99
95
  # lambda { do_something_risky }.should_not throw_symbol(:that_was_risky, culprit)
100
- def throw_symbol(sym=nil)
101
- Matchers::ThrowSymbol.new(sym)
96
+ def throw_symbol(expected_symbol = nil, expected_arg=nil)
97
+ Matchers::ThrowSymbol.new(expected_symbol, expected_arg)
102
98
  end
103
99
  end
104
100
  end
data/lib/spec/matchers.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'spec/matchers/extensions/instance_exec'
1
+ require 'spec/extensions/instance_exec'
2
2
  require 'spec/matchers/pretty'
3
3
  require 'spec/matchers/matcher'
4
4
  require 'spec/matchers/operator_matcher'
@@ -18,7 +18,7 @@ require 'spec/matchers/include'
18
18
  require 'spec/matchers/match'
19
19
  require 'spec/matchers/match_array'
20
20
  require 'spec/matchers/method_missing'
21
- require 'spec/matchers/raise_error'
21
+ require 'spec/matchers/raise_exception'
22
22
  require 'spec/matchers/respond_to'
23
23
  require 'spec/matchers/satisfy'
24
24
  require 'spec/matchers/simple_matcher'
@@ -139,6 +139,25 @@ module Spec
139
139
  # <tt>failure_message_for_should_not</tt>) are passed the actual value (the
140
140
  # receiver of <tt>should</tt> or <tt>should_not</tt>).
141
141
  #
142
+ # You can also create matchers that obey a fluent interface using the
143
+ # <tt>chain</tt> method:
144
+ #
145
+ # Spec::Matchers.define :tip do |expected_tip|
146
+ # chain :on do |bill|
147
+ # @bill = bill
148
+ # end
149
+ #
150
+ # match do |person|
151
+ # person.tip_for(bill) == expected_tip
152
+ # end
153
+ # end
154
+ #
155
+ # This matcher can be used as follows:
156
+ #
157
+ # describe Customer do
158
+ # it { should tip(10).on(50) }
159
+ # end
160
+ #
142
161
  # === Custom Matcher from scratch
143
162
  #
144
163
  # You could also write a custom matcher from scratch, as follows: