rspec 1.2.6 → 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/History.rdoc +22 -0
  2. data/Manifest.txt +9 -4
  3. data/Rakefile +13 -12
  4. data/Upgrade.rdoc +1 -1
  5. data/features/command_line/line_number_option.feature +56 -0
  6. data/features/command_line/line_number_option_with_example_with_no_name.feature +22 -0
  7. data/features/mocks/stub_implementation.feature +26 -0
  8. data/lib/autotest/rspec.rb +7 -7
  9. data/lib/spec/autorun.rb +1 -1
  10. data/lib/spec/deprecation.rb +3 -3
  11. data/lib/spec/dsl.rb +0 -1
  12. data/lib/spec/dsl/main.rb +6 -6
  13. data/lib/spec/example.rb +28 -29
  14. data/lib/spec/example/args_and_options.rb +1 -1
  15. data/lib/spec/example/before_and_after_hooks.rb +10 -10
  16. data/lib/spec/example/errors.rb +8 -3
  17. data/lib/spec/example/example_group.rb +0 -1
  18. data/lib/spec/example/example_group_factory.rb +3 -3
  19. data/lib/spec/example/example_group_hierarchy.rb +10 -10
  20. data/lib/spec/example/example_group_methods.rb +37 -29
  21. data/lib/spec/example/example_group_proxy.rb +9 -10
  22. data/lib/spec/example/example_matcher.rb +3 -3
  23. data/lib/spec/example/example_methods.rb +11 -11
  24. data/lib/spec/example/example_proxy.rb +5 -5
  25. data/lib/spec/example/module_reopening_fix.rb +7 -7
  26. data/lib/spec/example/pending.rb +1 -1
  27. data/lib/spec/example/predicate_matchers.rb +0 -1
  28. data/lib/spec/example/shared_example_group.rb +5 -5
  29. data/lib/spec/example/subject.rb +12 -16
  30. data/lib/spec/expectations/extensions/kernel.rb +1 -1
  31. data/lib/spec/expectations/fail_with.rb +4 -0
  32. data/lib/spec/matchers/generated_descriptions.rb +4 -16
  33. data/lib/spec/matchers/match.rb +5 -4
  34. data/lib/spec/matchers/matcher.rb +21 -3
  35. data/lib/spec/matchers/operator_matcher.rb +1 -1
  36. data/lib/spec/mocks/errors.rb +1 -1
  37. data/lib/spec/mocks/message_expectation.rb +3 -2
  38. data/lib/spec/mocks/methods.rb +8 -5
  39. data/lib/spec/mocks/proxy.rb +2 -2
  40. data/lib/spec/rake/spectask.rb +9 -3
  41. data/lib/spec/runner.rb +1 -1
  42. data/lib/spec/runner/{spec_parser.rb → line_number_query.rb} +20 -9
  43. data/lib/spec/runner/options.rb +10 -2
  44. data/lib/spec/version.rb +3 -2
  45. data/spec/autotest/failed_results_re_spec.rb +7 -0
  46. data/spec/spec/example/example_group_methods_spec.rb +61 -0
  47. data/spec/spec/example/example_matcher_spec.rb +7 -0
  48. data/spec/spec/example/example_methods_spec.rb +35 -7
  49. data/spec/spec/expectations/fail_with_spec.rb +18 -1
  50. data/spec/spec/matchers/match_spec.rb +20 -0
  51. data/spec/spec/matchers/matcher_spec.rb +27 -28
  52. data/spec/spec/matchers/operator_matcher_spec.rb +1 -1
  53. data/spec/spec/mocks/bug_report_10263_spec.rb +4 -1
  54. data/spec/spec/mocks/bug_report_830_spec.rb +21 -0
  55. data/spec/spec/mocks/options_hash_spec.rb +1 -1
  56. data/spec/spec/mocks/stub_chain_spec.rb +7 -0
  57. data/spec/spec/mocks/stub_implementation_spec.rb +31 -0
  58. data/spec/spec/rake/spectask_spec.rb +150 -0
  59. data/spec/spec/runner/{spec_parser/spec_parser_fixture.rb → line_number_query/line_number_query_fixture.rb} +4 -4
  60. data/spec/spec/runner/{spec_parser_spec.rb → line_number_query_spec.rb} +31 -10
  61. data/spec/spec/runner/option_parser_spec.rb +1 -1
  62. data/spec/spec/runner/options_spec.rb +33 -25
  63. metadata +15 -10
  64. data/.autotest +0 -5
@@ -1,10 +1,10 @@
1
1
  module Spec
2
2
  module Example
3
3
  module ExampleMethods
4
-
4
+
5
5
  extend Spec::Example::ModuleReopeningFix
6
6
  include Spec::Example::Subject::ExampleMethods
7
-
7
+
8
8
  def violated(message="")
9
9
  raise Spec::Expectations::ExpectationNotMetError.new(message)
10
10
  end
@@ -21,10 +21,10 @@ module Spec
21
21
  if description = @_proxy.description || ::Spec::Matchers.generated_description
22
22
  description
23
23
  else
24
- raise Spec::Example::NoDescriptionError.new("example", @_proxy.location)
24
+ Spec.warn Spec::Example::NoDescriptionError.message("example", @_proxy.location)
25
25
  end
26
26
  end
27
-
27
+
28
28
  def options # :nodoc:
29
29
  @_proxy.options
30
30
  end
@@ -32,7 +32,7 @@ module Spec
32
32
  def execute(run_options, instance_variables) # :nodoc:
33
33
  run_options.reporter.example_started(@_proxy)
34
34
  set_instance_variables_from_hash(instance_variables)
35
-
35
+
36
36
  execution_error = nil
37
37
  Timeout.timeout(run_options.timeout) do
38
38
  begin
@@ -51,12 +51,12 @@ module Spec
51
51
  run_options.reporter.example_finished(@_proxy.update(description), execution_error)
52
52
  success = execution_error.nil? || ExamplePendingError === execution_error
53
53
  end
54
-
54
+
55
55
  module BlockAliases
56
56
  alias_method :to, :should
57
57
  alias_method :to_not, :should_not
58
58
  end
59
-
59
+
60
60
  # Extends the submitted block with aliases to and to_not
61
61
  # for should and should_not. Allows expectations like this:
62
62
  #
@@ -115,10 +115,10 @@ module Spec
115
115
  end
116
116
 
117
117
  private
118
-
118
+
119
119
  include Matchers
120
120
  include Pending
121
-
121
+
122
122
  def before_each_example
123
123
  setup_mocks_for_rspec
124
124
  run_before_each
@@ -134,7 +134,7 @@ module Spec
134
134
  def described_class
135
135
  self.class.described_class
136
136
  end
137
-
137
+
138
138
  def description_args
139
139
  self.class.description_args
140
140
  end
@@ -142,7 +142,7 @@ module Spec
142
142
  def example_group_hierarchy
143
143
  self.class.example_group_hierarchy
144
144
  end
145
-
145
+
146
146
  end
147
147
  end
148
148
  end
@@ -7,32 +7,32 @@ module Spec
7
7
  def initialize(description=nil, options={}, location=nil) # :nodoc:
8
8
  @description, @options, @location = description, options, location
9
9
  end
10
-
10
+
11
11
  # Optional hash passed to the example declaration
12
12
  attr_reader :options
13
13
 
14
14
  # This is the docstring passed to the <tt>it()</tt> method or any
15
15
  # of its aliases
16
16
  attr_reader :description
17
-
17
+
18
18
  # The file and line number at which the represented example
19
19
  # was declared. This is extracted from <tt>caller</tt>, and is therefore
20
20
  # formatted as an individual line in a backtrace.
21
21
  attr_reader :location
22
-
22
+
23
23
  # Deprecated - use location()
24
24
  def backtrace
25
25
  Spec.deprecate("ExampleProxy#backtrace","ExampleProxy#location")
26
26
  location
27
27
  end
28
-
28
+
29
29
  # Convenience method for example group - updates the value of
30
30
  # <tt>description</tt> and returns self.
31
31
  def update(description) # :nodoc:
32
32
  @description = description
33
33
  self
34
34
  end
35
-
35
+
36
36
  def ==(other) # :nodoc:
37
37
  (other.description == description) & (other.location == location)
38
38
  end
@@ -2,23 +2,23 @@ module Spec
2
2
  module Example
3
3
  # When you reopen a module that is included in another module that is included in a class,
4
4
  # the new material you define does not make it to the class. This fixes that.
5
- #
5
+ #
6
6
  # == Example
7
- #
7
+ #
8
8
  # module M1; end
9
- #
9
+ #
10
10
  # module M2
11
11
  # def foo; "FOO"; end
12
12
  # end
13
- #
13
+ #
14
14
  # class C
15
15
  # include M1
16
16
  # end
17
- #
17
+ #
18
18
  # module M1
19
19
  # include M2
20
20
  # end
21
- #
21
+ #
22
22
  # c = C.new
23
23
  # c.foo
24
24
  # NoMethodError: undefined method `foo' for #<C:0x5e89a4>
@@ -40,4 +40,4 @@ module Spec
40
40
  end
41
41
  end
42
42
  end
43
- end
43
+ end
@@ -1,5 +1,5 @@
1
1
  module Spec
2
- module Example
2
+ module Example
3
3
  module Pending
4
4
  def pending(message = "TODO")
5
5
  if block_given?
@@ -44,4 +44,3 @@ module Spec
44
44
  end
45
45
  end
46
46
  end
47
-
@@ -7,7 +7,7 @@ module Spec
7
7
  shared_example_groups << new_example_group unless already_registered?(new_example_group)
8
8
  new_example_group
9
9
  end
10
-
10
+
11
11
  def find(example_group_description)
12
12
  shared_example_groups.find {|b| b.description == example_group_description}
13
13
  end
@@ -15,21 +15,21 @@ module Spec
15
15
  def clear
16
16
  shared_example_groups.clear
17
17
  end
18
-
18
+
19
19
  def include?(group)
20
20
  shared_example_groups.include?(group)
21
21
  end
22
-
22
+
23
23
  def count
24
24
  shared_example_groups.length
25
25
  end
26
26
 
27
27
  private
28
-
28
+
29
29
  def shared_example_groups
30
30
  @shared_example_groups ||= []
31
31
  end
32
-
32
+
33
33
  def already_registered?(new_example_group)
34
34
  existing_example_group = find(new_example_group.description)
35
35
  return false unless existing_example_group
@@ -18,11 +18,11 @@ module Spec
18
18
  block.nil? ?
19
19
  explicit_subject || implicit_subject : @explicit_subject_block = block
20
20
  end
21
-
21
+
22
22
  attr_reader :explicit_subject_block # :nodoc:
23
-
23
+
24
24
  private
25
-
25
+
26
26
  def explicit_subject
27
27
  group = self
28
28
  while group.respond_to?(:explicit_subject_block)
@@ -30,13 +30,17 @@ module Spec
30
30
  group = group.superclass
31
31
  end
32
32
  end
33
-
33
+
34
34
  def implicit_subject
35
35
  (described_class ? lambda {described_class.new} : lambda {description_args.first})
36
36
  end
37
37
  end
38
-
38
+
39
39
  module ExampleMethods
40
+
41
+ alias_method :__should_for_example_group__, :should
42
+ alias_method :__should_not_for_example_group__, :should_not
43
+
40
44
  # Returns the subject defined in ExampleGroupMethods#subject. The
41
45
  # subject block is only executed once per example, the result of which
42
46
  # is cached and returned by any subsequent calls to +subject+.
@@ -76,11 +80,7 @@ module Spec
76
80
  # it { should be_eligible_to_vote }
77
81
  # end
78
82
  def should(matcher=nil)
79
- if matcher
80
- subject.should(matcher)
81
- else
82
- subject.should
83
- end
83
+ self == subject ? self.__should_for_example_group__(matcher) : subject.should(matcher)
84
84
  end
85
85
 
86
86
  # Just like +should+, +should_not+ delegates to the subject (implicit or
@@ -92,13 +92,9 @@ module Spec
92
92
  # it { should_not be_eligible_to_vote }
93
93
  # end
94
94
  def should_not(matcher=nil)
95
- if matcher
96
- subject.should_not(matcher)
97
- else
98
- subject.should_not
99
- end
95
+ self == subject ? self.__should_not_for_example_group__(matcher) : subject.should_not(matcher)
100
96
  end
101
97
  end
102
98
  end
103
99
  end
104
- end
100
+ end
@@ -26,7 +26,7 @@ module Kernel
26
26
  def should(matcher=nil, &block)
27
27
  Spec::Expectations::PositiveExpectationHandler.handle_matcher(self, matcher, &block)
28
28
  end
29
-
29
+
30
30
  # :call-seq:
31
31
  # should_not(matcher)
32
32
  # should_not == expected
@@ -9,6 +9,10 @@ module Spec
9
9
  # <code>expected</code> and <code>target</code>, passes them
10
10
  # to the differ to append a diff message to the failure message.
11
11
  def fail_with(message, expected=nil, target=nil) # :nodoc:
12
+ if message.nil?
13
+ raise ArgumentError, "Failure message is nil. Does your matcher define the " +
14
+ "appropriate failure_message_for_* method to return a string?"
15
+ end
12
16
  if (Array === message) & (message.length == 3)
13
17
  ::Spec.warn(<<-NOTICE
14
18
 
@@ -1,19 +1,7 @@
1
1
  module Spec
2
2
  module Matchers
3
- def self.last_matcher
4
- @last_matcher
5
- end
6
-
7
- def self.last_matcher=(last_matcher)
8
- @last_matcher = last_matcher
9
- end
10
-
11
- def self.last_should
12
- @last_should
13
- end
14
-
15
- def self.last_should=(last_should)
16
- @last_should = last_should
3
+ class << self
4
+ attr_accessor :last_matcher, :last_should # :nodoc:
17
5
  end
18
6
 
19
7
  def self.clear_generated_description
@@ -26,7 +14,7 @@ module Spec
26
14
  "#{last_should.to_s.gsub('_',' ')} #{last_description}"
27
15
  end
28
16
 
29
- private
17
+ private
30
18
 
31
19
  def self.last_description
32
20
  last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
@@ -38,7 +26,7 @@ or this:
38
26
 
39
27
  it { should matcher }
40
28
 
41
- the runner expects the matcher to have a #description method. You should either
29
+ RSpec expects the matcher to have a #description method. You should either
42
30
  add a String to the example this matcher is being used in, or give it a
43
31
  description method. Then you won't have to suffer this lengthy warning again.
44
32
  MESSAGE
@@ -1,18 +1,19 @@
1
1
  module Spec
2
2
  module Matchers
3
3
  # :call-seq:
4
- # should match(regexp)
5
- # should_not match(regexp)
4
+ # should match(pattern)
5
+ # should_not match(pattern)
6
6
  #
7
- # Given a Regexp, passes if actual =~ regexp
7
+ # Given a Regexp or String, passes if actual.match(pattern)
8
8
  #
9
9
  # == Examples
10
10
  #
11
11
  # email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
12
+ # email.should match("@example.com")
12
13
  def match(expected)
13
14
  Matcher.new :match, expected do |_expected_|
14
15
  match do |actual|
15
- actual =~ _expected_
16
+ actual.match(_expected_)
16
17
  end
17
18
  end
18
19
  end
@@ -8,18 +8,19 @@ module Spec
8
8
  def initialize(name, *expected, &declarations)
9
9
  @name = name
10
10
  @expected = expected
11
- @declarations = declarations
12
11
  @diffable = false
13
12
  @messages = {
14
13
  :description => lambda {"#{name_to_sentence}#{expected_to_sentence}"},
15
14
  :failure_message_for_should => lambda {|actual| "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"},
16
15
  :failure_message_for_should_not => lambda {|actual| "expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"}
17
16
  }
17
+ making_declared_methods_public do
18
+ instance_exec(*@expected, &declarations)
19
+ end
18
20
  end
19
21
 
20
22
  def matches?(actual)
21
23
  @actual = actual
22
- instance_exec(*@expected, &@declarations)
23
24
  instance_exec(@actual, &@match_block)
24
25
  end
25
26
 
@@ -46,9 +47,26 @@ module Spec
46
47
  def diffable
47
48
  @diffable = true
48
49
  end
49
-
50
+
50
51
  private
51
52
 
53
+ def making_declared_methods_public # :nodoc:
54
+ # Our home-grown instance_exec in ruby 1.8.6 results in any methods
55
+ # declared in the block eval'd by instance_exec in the block to which we
56
+ # are yielding here are scoped private. This is NOT the case for Ruby
57
+ # 1.8.7 or 1.9.
58
+ #
59
+ # Also, due some crazy scoping that I don't understand, these methods
60
+ # are actually available in the specs (something about the matcher being
61
+ # defined in the scope of Spec::Matchers or within an example), so not
62
+ # doing the following will not cause specs to fail, but they *will*
63
+ # cause features to fail and that will make users unhappy. So don't.
64
+ orig_private_methods = private_methods
65
+ yield
66
+ st = (class << self; self; end)
67
+ (private_methods - orig_private_methods).each {|m| st.__send__ :public, m}
68
+ end
69
+
52
70
  def cache_or_call_cached(key, actual=nil, &block)
53
71
  block ? @messages[key] = block :
54
72
  actual.nil? ? @messages[key].call : @messages[key].call(actual)
@@ -68,7 +68,7 @@ module Spec
68
68
 
69
69
  class NegativeOperatorMatcher < OperatorMatcher #:nodoc:
70
70
  def __delegate_operator(actual, operator, expected)
71
- return true unless actual.__send__(operator, expected)
71
+ return false unless actual.__send__(operator, expected)
72
72
  return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
73
73
  end
74
74
 
@@ -1,6 +1,6 @@
1
1
  module Spec
2
2
  module Mocks
3
- class MockExpectationError < StandardError
3
+ class MockExpectationError < Exception
4
4
  end
5
5
 
6
6
  class AmbiguousReturnError < StandardError
@@ -8,7 +8,7 @@ module Spec
8
8
  attr_accessor :error_generator
9
9
  protected :error_generator, :error_generator=
10
10
 
11
- def initialize(error_generator, expectation_ordering, expected_from, sym, method_block, expected_received_count=1, opts={})
11
+ def initialize(error_generator, expectation_ordering, expected_from, sym, method_block, expected_received_count=1, opts={}, &implementation)
12
12
  @error_generator = error_generator
13
13
  @error_generator.opts = opts
14
14
  @expected_from = expected_from
@@ -27,6 +27,7 @@ module Spec
27
27
  @args_to_yield = []
28
28
  @failed_fast = nil
29
29
  @args_to_yield_were_cloned = false
30
+ @return_block = implementation
30
31
  end
31
32
 
32
33
  def build_child(expected_from, method_block, expected_received_count, opts={})
@@ -167,7 +168,7 @@ module Spec
167
168
  # Ruby 1.9 - when we set @return_block to return values
168
169
  # regardless of arguments, any arguments will result in
169
170
  # a "wrong number of arguments" error
170
- @return_block.arity > 0 ? @return_block.call(*args) : @return_block.call()
171
+ @return_block.arity == 0 ? @return_block.call : @return_block.call(*args)
171
172
  end
172
173
 
173
174
  def clone_args_to_yield(args)
@@ -9,21 +9,24 @@ module Spec
9
9
  __mock_proxy.add_negative_message_expectation(caller(1)[0], sym.to_sym, &block)
10
10
  end
11
11
 
12
- def stub!(sym_or_hash, opts={})
12
+ def stub!(sym_or_hash, opts={}, &block)
13
13
  if Hash === sym_or_hash
14
14
  sym_or_hash.each {|method, value| stub!(method).and_return value }
15
15
  else
16
- __mock_proxy.add_stub(caller(1)[0], sym_or_hash.to_sym, opts)
16
+ __mock_proxy.add_stub(caller(1)[0], sym_or_hash.to_sym, opts, &block)
17
17
  end
18
18
  end
19
19
 
20
20
  alias_method :stub, :stub!
21
21
 
22
22
  def stub_chain(*methods)
23
- while methods.length > 1
24
- stub!(methods.shift).and_return(self)
23
+ if methods.length > 1
24
+ next_in_chain = Object.new
25
+ stub!(methods.shift) {next_in_chain}
26
+ next_in_chain.stub_chain(*methods)
27
+ else
28
+ stub!(methods.shift)
25
29
  end
26
- stub!(methods.shift)
27
30
  end
28
31
 
29
32
  def received_message?(sym, *args, &block) #:nodoc: