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
@@ -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