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
@@ -56,9 +56,9 @@ module Spec
56
56
  @expectations.last
57
57
  end
58
58
 
59
- def add_stub(expected_from, sym, opts={})
59
+ def add_stub(expected_from, sym, opts={}, &implementation)
60
60
  __add sym
61
- @stubs.unshift MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, nil, :any, opts)
61
+ @stubs.unshift MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, nil, :any, opts, &implementation)
62
62
  @stubs.first
63
63
  end
64
64
 
@@ -118,6 +118,9 @@ module Spec
118
118
  # Use verbose output. If this is set to true, the task will print
119
119
  # the executed spec command to stdout. Defaults to false.
120
120
  attr_accessor :verbose
121
+
122
+ # Explicitly define the path to the ruby binary, or its proxy (e.g. multiruby)
123
+ attr_accessor :ruby_cmd
121
124
 
122
125
  # Defines a new task, using the name +name+.
123
126
  def initialize(name=:spec)
@@ -152,7 +155,7 @@ module Spec
152
155
  # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts]
153
156
  # or
154
157
  # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts]
155
- cmd_parts = [RUBY]
158
+ cmd_parts = [ruby_cmd || RUBY]
156
159
  cmd_parts += ruby_opts
157
160
  cmd_parts << %[-I"#{lib_path}"]
158
161
  cmd_parts << "-S rcov" if rcov
@@ -192,8 +195,11 @@ module Spec
192
195
  end
193
196
 
194
197
  def rcov_option_list # :nodoc:
195
- return "" unless rcov
196
- ENV['RCOV_OPTS'] || rcov_opts.join(" ") || ""
198
+ if rcov
199
+ ENV['RCOV_OPTS'] || rcov_opts.join(" ") || ""
200
+ else
201
+ ""
202
+ end
197
203
  end
198
204
 
199
205
  def spec_option_list # :nodoc:
@@ -6,7 +6,7 @@ require 'spec/runner/command_line'
6
6
  require 'spec/runner/drb_command_line'
7
7
  require 'spec/runner/backtrace_tweaker'
8
8
  require 'spec/runner/reporter'
9
- require 'spec/runner/spec_parser'
9
+ require 'spec/runner/line_number_query'
10
10
  require 'spec/runner/class_and_arguments_parser'
11
11
  require 'spec/runner/extensions/kernel'
12
12
 
@@ -1,7 +1,7 @@
1
1
  module Spec
2
2
  module Runner
3
3
  # Parses a spec file and finds the nearest example for a given line number.
4
- class SpecParser
4
+ class LineNumberQuery
5
5
  attr_reader :best_match
6
6
 
7
7
  def initialize(run_options)
@@ -12,14 +12,7 @@ module Spec
12
12
  def spec_name_for(file, line_number)
13
13
  best_match.clear
14
14
  file = File.expand_path(file)
15
- @run_options.example_groups.each do |example_group|
16
- next unless example_group.location
17
- consider_example_group_for_best_match(example_group, file, line_number)
18
-
19
- example_group.examples.each do |example|
20
- consider_example_for_best_match(example, example_group, file, line_number)
21
- end
22
- end
15
+ determine_best_match(file, line_number)
23
16
  if best_match[:example_group]
24
17
  if best_match[:example]
25
18
  "#{best_match[:example_group].description} #{best_match[:example].description}"
@@ -31,7 +24,25 @@ module Spec
31
24
  end
32
25
  end
33
26
 
27
+ def example_line_for(file, line_number)
28
+ determine_best_match(file, line_number)
29
+ best_match[:line]
30
+ end
31
+
34
32
  protected
33
+
34
+ def determine_best_match(file, line_number)
35
+ best_match.clear
36
+ file = File.expand_path(file)
37
+ @run_options.example_groups.each do |example_group|
38
+ next unless example_group.location
39
+ consider_example_group_for_best_match(example_group, file, line_number)
40
+
41
+ example_group.examples.each do |example|
42
+ consider_example_for_best_match(example, example_group, file, line_number)
43
+ end
44
+ end
45
+ end
35
46
 
36
47
  def consider_example_group_for_best_match(example_group, file, line_number)
37
48
  example_group_file, example_group_line = parse_location(example_group.location)
@@ -74,10 +74,18 @@ module Spec
74
74
  @files_loaded = false
75
75
  @out_used = nil
76
76
  end
77
-
77
+
78
78
  def add_example_group(example_group)
79
79
  @example_groups << example_group
80
80
  end
81
+
82
+ def line_number_requested?
83
+ !!line_number
84
+ end
85
+
86
+ def example_line
87
+ Spec::Runner::LineNumberQuery.new(self).example_line_for(files.first, line_number)
88
+ end
81
89
 
82
90
  def remove_example_group(example_group)
83
91
  @example_groups.delete(example_group)
@@ -340,7 +348,7 @@ module Spec
340
348
  error_stream.puts "You must specify one file, not a directory when providing a line number"
341
349
  exit(1) if stderr?
342
350
  else
343
- example = SpecParser.new(self).spec_name_for(files[0], line_number)
351
+ example = LineNumberQuery.new(self).spec_name_for(files[0], line_number)
344
352
  @examples = [example]
345
353
  end
346
354
  else
@@ -3,9 +3,10 @@ module Spec # :nodoc:
3
3
  unless defined? MAJOR
4
4
  MAJOR = 1
5
5
  MINOR = 2
6
- TINY = 6
6
+ TINY = 7
7
+ PRE = nil
7
8
 
8
- STRING = [MAJOR, MINOR, TINY].compact.join('.')
9
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
10
 
10
11
  SUMMARY = "rspec #{STRING}"
11
12
  end
@@ -8,6 +8,13 @@ describe "failed_results_re" do
8
8
  $2.should == "reason\n/path.rb:37:"
9
9
  end
10
10
 
11
+ it "should match a failure when matcher outputs multiple lines" do
12
+ re = Autotest::Rspec.new.failed_results_re
13
+ re =~ "1)\n'other example' FAILED\n\nreason line 1\nreason line 2\n\n(additional info)\n/path.rb:37:\n\n"
14
+ $1.should == "other example"
15
+ $2.should == "reason line 1\nreason line 2\n\n(additional info)\n/path.rb:37:"
16
+ end
17
+
11
18
  it "should match an Error" do
12
19
  re = Autotest::Rspec.new.failed_results_re
13
20
  re =~ "1)\nRuntimeError in 'this example'\nreason\n/path.rb:37:\n\n"
@@ -670,6 +670,67 @@ module Spec
670
670
  example_group.__send__ :run_after_all, true, {}, nil
671
671
  end
672
672
  end
673
+
674
+ describe "#examples_to_run" do
675
+ it "runs only the example identified by a line number" do
676
+ example_group = Class.new(ExampleGroupDouble).describe("this") do
677
+ it { 3.should == 3 }
678
+ it "has another example which raises" do
679
+ raise "this shouldn't have run"
680
+ end
681
+ end
682
+ options.examples << :ignore
683
+ options.line_number = __LINE__ - 6
684
+ options.files << __FILE__
685
+ example_group.run(options).should be_true
686
+ end
687
+
688
+ it "runs the example identified by a line number even if it's not the example line number" do
689
+ example_group = Class.new(ExampleGroupDouble).describe("this") do
690
+
691
+ it { raise "foo" }
692
+
693
+ end
694
+ options.examples << :ignore
695
+ options.line_number = __LINE__ - 3
696
+ options.files << __FILE__
697
+ example_group.run(options).should be_false
698
+ end
699
+
700
+ it "runs all the examples in the group " do
701
+ first_example_ran = false
702
+ second_example_ran = false
703
+ example_group = Class.new(ExampleGroupDouble).describe("this") do
704
+
705
+ it { first_example_ran = true }
706
+ it { second_example_ran = true }
707
+
708
+ end
709
+ options.line_number = __LINE__ - 6
710
+ options.files << __FILE__
711
+ options.examples << :ignore
712
+ example_group.run(options)
713
+ first_example_ran.should be_true
714
+ second_example_ran.should be_true
715
+ end
716
+
717
+ it "doesn't run any examples in another group" do
718
+ example_ran = false
719
+ example_group_1 = Class.new(ExampleGroupDouble).describe("this") do
720
+ it "ignore" do
721
+ example_ran = true
722
+ end
723
+ end
724
+ example_group_2 = Class.new(ExampleGroupDouble).describe("that") do
725
+ end
726
+ options.examples << :ignore
727
+ options.line_number = __LINE__ - 3
728
+ options.files << __FILE__
729
+ example_group_1.run(options)
730
+ example_group_2.run(options)
731
+ example_ran.should be_false
732
+ end
733
+ end
673
734
 
674
735
  end
675
736
  end
@@ -75,5 +75,12 @@ module Spec
75
75
  matcher.matches?(["no match1", "no match2"]).should == false
76
76
  end
77
77
  end
78
+
79
+ describe ExampleMatcher, "called with nil example" do
80
+ it "does not puke" do
81
+ matcher = ExampleMatcher.new("Foo::Bar", nil)
82
+ matcher.matches?(["anything"]).should == false
83
+ end
84
+ end
78
85
  end
79
86
  end
@@ -27,7 +27,7 @@ module Spec
27
27
  end
28
28
 
29
29
  describe "with an included module that is reopened" do
30
- it "should have repoened methods" do
30
+ it "should have reopened methods" do
31
31
  method(:module_that_is_reopened_method).should_not be_nil
32
32
  end
33
33
  end
@@ -56,11 +56,26 @@ module Spec
56
56
  @example_group.run(@options).should be_true
57
57
  end
58
58
  end
59
+
60
+ context "in an ExampleGroup using 'self' as an explicit subject" do
61
+ it "delegates matcher to the ExampleGroup" do
62
+ @example_group.describe(::Thing)
63
+ @example_group.subject { self }
64
+ @example_group.example { should == self }
65
+ @example_group.example { should eql(self) }
66
+ @example_group.example do
67
+ self.instance_eval("def method_ok?; true end")
68
+ should be_method_ok
69
+ end
70
+ @example_group.run(@options).should be_true
71
+ end
72
+ end
59
73
  end
60
74
 
61
75
  describe "#should_not" do
62
76
  before(:each) do
63
77
  @example_group = Class.new(ExampleGroupDouble)
78
+ @options = ::Spec::Runner::Options.new(StringIO.new, StringIO.new)
64
79
  end
65
80
 
66
81
  context "in an ExampleGroup with an implicit subject" do
@@ -68,7 +83,7 @@ module Spec
68
83
  @example_group.describe(::Thing)
69
84
  @example_group.example { should_not == ::Thing.new(:other) }
70
85
  @example_group.example { should_not eql(::Thing.new(:other)) }
71
- @example_group.run(::Spec::Runner::Options.new(StringIO.new, StringIO.new)).should be_true
86
+ @example_group.run(@options).should be_true
72
87
  end
73
88
  end
74
89
 
@@ -78,7 +93,21 @@ module Spec
78
93
  @example_group.subject { ::Thing.new(:other) }
79
94
  @example_group.example { should_not == ::Thing.new(:default) }
80
95
  @example_group.example { should_not eql(::Thing.new(:default)) }
81
- @example_group.run(::Spec::Runner::Options.new(StringIO.new, StringIO.new)).should be_true
96
+ @example_group.run(@options).should be_true
97
+ end
98
+ end
99
+
100
+ context "in an ExampleGroup using 'self' as an explicit subject" do
101
+ it "delegates matcher to the ExampleGroup" do
102
+ @example_group.describe(::Thing)
103
+ @example_group.subject { self }
104
+ @example_group.example { should_not == ::Thing.new(:default) }
105
+ @example_group.example { should_not eql(::Thing.new(:default)) }
106
+ @example_group.example do
107
+ self.instance_eval("def method_ok?; false end")
108
+ should_not be_method_ok
109
+ end
110
+ @example_group.run(@options).should be_true
82
111
  end
83
112
  end
84
113
  end
@@ -109,12 +138,11 @@ module Spec
109
138
  Spec::Matchers.stub!(:generated_description).and_return('this message')
110
139
  example.description.should == "this message"
111
140
  end
112
- it "raises if there is no supplied or generated description" do
141
+ it "warns if there is no supplied or generated description" do
113
142
  example = ExampleGroupDouble.new ExampleProxy.new(nil, {}, "this backtrace") do; end
114
143
  Spec::Matchers.stub!(:generated_description).and_return(nil)
115
- lambda do
116
- example.description
117
- end.should raise_error(/No description supplied for example declared on this backtrace/)
144
+ Spec.should_receive(:warn).with("No description supplied for example declared on this backtrace")
145
+ example.description
118
146
  end
119
147
  end
120
148
 
@@ -64,7 +64,24 @@ describe Spec::Expectations, "#fail_with with diff" do
64
64
  Spec::Expectations.fail_with "the message", lambda {}, lambda {}
65
65
  }.should fail_with("the message")
66
66
  end
67
-
67
+
68
+ after(:each) do
69
+ Spec::Expectations.differ = @old_differ
70
+ end
71
+ end
72
+
73
+ describe Spec::Expectations, "#fail_with with a nil message" do
74
+ before(:each) do
75
+ @old_differ = Spec::Expectations.differ
76
+ Spec::Expectations.differ = nil
77
+ end
78
+
79
+ it "should handle just a message" do
80
+ lambda {
81
+ Spec::Expectations.fail_with nil
82
+ }.should raise_error(ArgumentError, /Failure message is nil\. Does your matcher define the appropriate failure_message_for_\* method to return a string\?/)
83
+ end
84
+
68
85
  after(:each) do
69
86
  Spec::Expectations.differ = @old_differ
70
87
  end
@@ -5,11 +5,21 @@ describe "should match(expected)" do
5
5
  "string".should match(/tri/)
6
6
  end
7
7
 
8
+ it "should pass when target (String) matches expected (String)" do
9
+ "string".should match("tri")
10
+ end
11
+
8
12
  it "should fail when target (String) does not match expected (Regexp)" do
9
13
  lambda {
10
14
  "string".should match(/rings/)
11
15
  }.should fail
12
16
  end
17
+
18
+ it "should fail when target (String) does not match expected (String)" do
19
+ lambda {
20
+ "string".should match("rings")
21
+ }.should fail
22
+ end
13
23
 
14
24
  it "should provide message, expected and actual on failure" do
15
25
  matcher = match(/rings/)
@@ -23,12 +33,22 @@ describe "should_not match(expected)" do
23
33
  "string".should_not match(/rings/)
24
34
  end
25
35
 
36
+ it "should pass when target (String) matches does not match (String)" do
37
+ "string".should_not match("rings")
38
+ end
39
+
26
40
  it "should fail when target (String) matches expected (Regexp)" do
27
41
  lambda {
28
42
  "string".should_not match(/tri/)
29
43
  }.should fail
30
44
  end
31
45
 
46
+ it "should fail when target (String) matches expected (String)" do
47
+ lambda {
48
+ "string".should_not match("tri")
49
+ }.should fail
50
+ end
51
+
32
52
  it "should provide message, expected and actual on failure" do
33
53
  matcher = match(/tri/)
34
54
  matcher.matches?("string")
@@ -13,7 +13,6 @@ module Spec
13
13
  end
14
14
 
15
15
  it "provides a default description" do
16
- @matcher.matches?(0)
17
16
  @matcher.description.should == "be a multiple of 3"
18
17
  end
19
18
 
@@ -29,29 +28,17 @@ module Spec
29
28
  end
30
29
 
31
30
  it "is not diffable by default" do
32
- matcher = Spec::Matchers::Matcher.new(:name) do
33
- match {|actual|}
34
- end
35
- matcher.matches?(0)
31
+ matcher = Spec::Matchers::Matcher.new(:name) {}
36
32
  matcher.should_not be_diffable
37
33
  end
38
34
 
39
35
  it "is diffable when told to be" do
40
- matcher = Spec::Matchers::Matcher.new(:name) do
41
- match {|actual|}
42
- diffable
43
- end
44
- matcher.matches?(0)
36
+ matcher = Spec::Matchers::Matcher.new(:name) { diffable }
45
37
  matcher.should be_diffable
46
38
  end
47
39
 
48
40
  it "provides expected" do
49
- matcher = Spec::Matchers::Matcher.new(:name, 'expected string') do
50
- match {|actual|}
51
- end
52
-
53
- matcher.matches?('actual string')
54
-
41
+ matcher = Spec::Matchers::Matcher.new(:name, 'expected string') {}
55
42
  matcher.expected.should == ['expected string']
56
43
  end
57
44
 
@@ -92,7 +79,6 @@ module Spec
92
79
  end
93
80
 
94
81
  it "overrides the description" do
95
- @matcher.matches?(true)
96
82
  @matcher.description.should == "be the boolean true"
97
83
  end
98
84
 
@@ -181,20 +167,33 @@ module Spec
181
167
  end
182
168
  end
183
169
 
184
- context "with helper methods" do
185
- it "does something" do
186
- matcher = Spec::Matchers::Matcher.new(:be_similar_to, [1,2,3]) do |sample|
187
- match do |actual|
188
- similar?(sample, actual)
189
- end
170
+ it "supports helper methods" do
171
+ matcher = Spec::Matchers::Matcher.new(:be_similar_to, [1,2,3]) do |sample|
172
+ match do |actual|
173
+ similar?(sample, actual)
174
+ end
190
175
 
191
- def similar?(a, b)
192
- a.sort == b.sort
193
- end
176
+ def similar?(a, b)
177
+ a.sort == b.sort
194
178
  end
195
-
196
- matcher.matches?([2,3,1]).should be_true
197
179
  end
180
+
181
+ matcher.matches?([2,3,1]).should be_true
182
+ end
183
+
184
+ it "supports fluent interface" do
185
+ matcher = Spec::Matchers::Matcher.new(:first_word) do
186
+ def second_word
187
+ self
188
+ end
189
+ end
190
+
191
+ matcher.second_word.should == matcher
192
+ end
193
+
194
+ it "treats method missing normally for undeclared methods" do
195
+ matcher = Spec::Matchers::Matcher.new(:ignore) { }
196
+ expect { matcher.non_existent_method }.to raise_error(NoMethodError)
198
197
  end
199
198
 
200
199
  end