rspec 1.2.6 → 1.2.7

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 (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: