rspec-core 2.9.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/.yardopts +4 -1
  2. data/Changelog.md +20 -0
  3. data/README.md +10 -4
  4. data/features/command_line/format_option.feature +1 -1
  5. data/features/expectation_framework_integration/configure_expectation_framework.feature +20 -7
  6. data/features/hooks/around_hooks.feature +1 -1
  7. data/features/hooks/before_and_after_hooks.feature +5 -5
  8. data/features/hooks/filtering.feature +2 -2
  9. data/features/pending/pending_examples.feature +2 -2
  10. data/lib/rspec/core/configuration_options.rb +4 -3
  11. data/lib/rspec/core/example.rb +37 -22
  12. data/lib/rspec/core/example_group.rb +18 -20
  13. data/lib/rspec/core/formatters/base_formatter.rb +2 -8
  14. data/lib/rspec/core/formatters/base_text_formatter.rb +13 -4
  15. data/lib/rspec/core/hooks.rb +120 -77
  16. data/lib/rspec/core/let.rb +14 -6
  17. data/lib/rspec/core/metadata.rb +10 -2
  18. data/lib/rspec/core/subject.rb +34 -13
  19. data/lib/rspec/core/version.rb +1 -1
  20. data/lib/rspec/core/world.rb +0 -4
  21. data/spec/rspec/core/configuration_options_spec.rb +8 -2
  22. data/spec/rspec/core/drb_options_spec.rb +1 -1
  23. data/spec/rspec/core/example_group_spec.rb +2 -2
  24. data/spec/rspec/core/example_spec.rb +39 -16
  25. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +17 -7
  26. data/spec/rspec/core/hooks_spec.rb +117 -10
  27. data/spec/rspec/core/metadata_spec.rb +13 -3
  28. data/spec/rspec/core/pending_example_spec.rb +3 -2
  29. data/spec/rspec/core/subject_spec.rb +2 -0
  30. data/spec/spec_helper.rb +1 -0
  31. data/spec/support/config_options_helper.rb +0 -3
  32. data/spec/support/helper_methods.rb +5 -0
  33. metadata +153 -142
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Core
3
3
  module Version
4
- STRING = '2.9.0'
4
+ STRING = '2.10.0'
5
5
  end
6
6
  end
7
7
  end
@@ -115,10 +115,6 @@ module RSpec
115
115
  end
116
116
  end
117
117
 
118
- def find_hook(hook, scope, group, example = nil)
119
- @configuration.find_hook(hook, scope, group, example)
120
- end
121
-
122
118
  private
123
119
 
124
120
  def declaration_line_numbers
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'ostruct'
3
3
 
4
- describe RSpec::Core::ConfigurationOptions do
4
+ describe RSpec::Core::ConfigurationOptions, :fakefs do
5
5
  include ConfigOptionsHelper
6
6
 
7
7
  it "warns when HOME env var is not set", :unless => (RUBY_PLATFORM == 'java') do
@@ -316,11 +316,12 @@ describe RSpec::Core::ConfigurationOptions do
316
316
  it "merges global, local, SPEC_OPTS, and CLI" do
317
317
  File.open("./.rspec", "w") {|f| f << "--line 37"}
318
318
  File.open("~/.rspec", "w") {|f| f << "--color"}
319
- ENV["SPEC_OPTS"] = "--debug"
319
+ ENV["SPEC_OPTS"] = "--debug --example 'foo bar'"
320
320
  options = parse_options("--drb")
321
321
  options[:color].should be_true
322
322
  options[:line_numbers].should eq(["37"])
323
323
  options[:debug].should be_true
324
+ options[:full_description].should eq(/foo\ bar/)
324
325
  options[:drb].should be_true
325
326
  end
326
327
 
@@ -350,6 +351,11 @@ describe RSpec::Core::ConfigurationOptions do
350
351
  options[:format].should be_nil
351
352
  options[:color].should be_true
352
353
  end
354
+ it "parses -e 'full spec description'" do
355
+ File.open("./custom.opts", "w") {|f| f << "-e 'The quick brown fox jumps over the lazy dog'"}
356
+ options = parse_options("-O", "./custom.opts")
357
+ options[:full_description].should == /The\ quick\ brown\ fox\ jumps\ over\ the\ lazy\ dog/
358
+ end
353
359
  end
354
360
  end
355
361
  end
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- describe RSpec::Core::DrbOptions do
3
+ describe RSpec::Core::DrbOptions, :fakefs do
4
4
  include ConfigOptionsHelper
5
5
 
6
6
  describe "#drb_argv" do
@@ -345,11 +345,11 @@ module RSpec::Core
345
345
  end
346
346
 
347
347
  it "adds the the file_path to metadata" do
348
- ExampleGroup.describe(Object) { }.metadata[:example_group][:file_path].should eq(__FILE__)
348
+ ExampleGroup.describe(Object) { }.metadata[:example_group][:file_path].should eq(relative_path(__FILE__))
349
349
  end
350
350
 
351
351
  it "has a reader for file_path" do
352
- ExampleGroup.describe(Object) { }.file_path.should eq(__FILE__)
352
+ ExampleGroup.describe(Object) { }.file_path.should eq(relative_path(__FILE__))
353
353
  end
354
354
 
355
355
  it "adds the line_number to metadata" do
@@ -45,11 +45,7 @@ describe RSpec::Core::Example, :parent_metadata => 'sample' do
45
45
  end
46
46
  end
47
47
 
48
- describe "auto-generated example descriptions" do
49
- let(:generated_description) { "the generated description" }
50
- let(:rspec_example) { example_group.specify { 5.should eq(5) } }
51
- before(:each) { RSpec::Matchers.stub(:generated_description => generated_description) }
52
-
48
+ describe "when there is no explicit description" do
53
49
  def expect_with(*frameworks)
54
50
  RSpec.configuration.stub(:expecting_with_rspec?).and_return(frameworks.include?(:rspec))
55
51
 
@@ -65,35 +61,62 @@ describe RSpec::Core::Example, :parent_metadata => 'sample' do
65
61
  context "when `expect_with :rspec` is configured" do
66
62
  before(:each) { expect_with :rspec }
67
63
 
68
- it "generates a description for an example with no description" do
69
- expect {
70
- example_group.run
71
- }.to change { rspec_example.metadata[:description] }.from("").to(generated_description)
64
+ it "uses the matcher-generated description" do
65
+ example_group.example { 5.should eq(5) }
66
+ example_group.run
67
+ example_group.examples.first.description.should eq("should eq 5")
68
+ end
69
+
70
+ it "uses the file and line number if there is no matcher-generated description" do
71
+ example = example_group.example {}
72
+ example_group.run
73
+ example.description.should match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 2}/)
74
+ end
75
+
76
+ it "uses the file and line number if there is an error before the matcher" do
77
+ example = example_group.example { 5.should eq(5) }
78
+ example_group.before { raise }
79
+ example_group.run
80
+ example.description.should match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 3}/)
72
81
  end
73
82
  end
74
83
 
75
84
  context "when `expect_with :rspec, :stdlib` is configured" do
76
85
  before(:each) { expect_with :rspec, :stdlib }
77
86
 
78
- it "generates a description for an example with no description" do
79
- expect {
80
- example_group.run
81
- }.to change { rspec_example.metadata[:description] }.from("").to(generated_description)
87
+ it "uses the matcher-generated description" do
88
+ example_group.example { 5.should eq(5) }
89
+ example_group.run
90
+ example_group.examples.first.description.should eq("should eq 5")
91
+ end
92
+
93
+ it "uses the file and line number if there is no matcher-generated description" do
94
+ example = example_group.example {}
95
+ example_group.run
96
+ example.description.should match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 2}/)
97
+ end
98
+
99
+ it "uses the file and line number if there is an error before the matcher" do
100
+ example = example_group.example { 5.should eq(5) }
101
+ example_group.before { raise }
102
+ example_group.run
103
+ example.description.should match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 3}/)
82
104
  end
83
105
  end
84
106
 
85
107
  context "when `expect_with :stdlib` is configured" do
86
- let!(:stdlib_example) { example_group.specify { assert 5 == 5 } }
87
108
  before(:each) { expect_with :stdlib }
88
109
 
89
110
  it "does not attempt to get the generated description from RSpec::Matchers" do
90
111
  RSpec::Matchers.should_not_receive(:generated_description)
112
+ example_group.example { assert 5 == 5 }
91
113
  example_group.run
92
114
  end
93
115
 
94
- it "fails an example with no description" do
116
+ it "uses the file and line number" do
117
+ example = example_group.example { assert 5 == 5 }
95
118
  example_group.run
96
- stdlib_example.should have_failed_with(NotImplementedError)
119
+ example.description.should match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 2}/)
97
120
  end
98
121
  end
99
122
  end
@@ -27,7 +27,7 @@ describe RSpec::Core::Formatters::BaseTextFormatter do
27
27
  line = __LINE__ - 2
28
28
  group.run(formatter)
29
29
  formatter.dump_commands_to_rerun_failed_examples
30
- output.string.should include("rspec #{RSpec::Core::Formatters::BaseFormatter::relative_path("#{__FILE__}:#{line}")} # example group fails")
30
+ output.string.should include("rspec #{RSpec::Core::Metadata::relative_path("#{__FILE__}:#{line}")} # example group fails")
31
31
  end
32
32
  end
33
33
 
@@ -57,6 +57,12 @@ describe RSpec::Core::Formatters::BaseTextFormatter do
57
57
  group.example("example name") { raise exception_without_message }
58
58
  expect { run_all_and_dump_failures }.not_to raise_error(NoMethodError)
59
59
  end
60
+
61
+ it "preserves ancestry" do
62
+ example = group.example("example name") { raise "something" }
63
+ run_all_and_dump_failures
64
+ example.example_group.ancestors.size.should == 1
65
+ end
60
66
  end
61
67
 
62
68
  context "with an exception class other than RSpec" do
@@ -315,13 +321,12 @@ describe RSpec::Core::Formatters::BaseTextFormatter do
315
321
 
316
322
  describe "#dump_profile" do
317
323
  before do
318
- formatter.stub(:examples) do
319
- group = RSpec::Core::ExampleGroup.describe("group") do
320
- example("example")
321
- end
322
- group.run(double('reporter').as_null_object)
323
- group.examples
324
+ group = RSpec::Core::ExampleGroup.describe("group") do
325
+ example("example") { sleep 0.1 }
324
326
  end
327
+ group.run(double('reporter').as_null_object)
328
+
329
+ formatter.stub(:examples) { group.examples }
325
330
  end
326
331
 
327
332
  it "names the example" do
@@ -340,5 +345,10 @@ describe RSpec::Core::Formatters::BaseTextFormatter do
340
345
 
341
346
  output.string.should =~ /#{filename}\:#{__LINE__ - 21}/
342
347
  end
348
+
349
+ it "prints the percentage taken from the total runtime" do
350
+ formatter.dump_profile
351
+ output.string.should =~ /, 100.0% of total time\):/
352
+ end
343
353
  end
344
354
  end
@@ -15,7 +15,7 @@ module RSpec::Core
15
15
  define_method :metadata_hash do |*args|
16
16
  instance = HooksHost.new
17
17
  args.unshift scope if scope
18
- hooks = instance.send(type, *args) { }
18
+ hooks = instance.send(type, *args) {}
19
19
  hooks.first.options
20
20
  end
21
21
  end
@@ -33,19 +33,19 @@ module RSpec::Core
33
33
  let(:instance) { HooksHost.new }
34
34
 
35
35
  it "defaults to :each scope if no arguments are given" do
36
- hooks = instance.send(type) { }
36
+ hooks = instance.send(type) {}
37
37
  hook = hooks.first
38
38
  instance.hooks[type][:each].should include(hook)
39
39
  end
40
40
 
41
41
  it "defaults to :each scope if the only argument is a metadata hash" do
42
- hooks = instance.send(type, :foo => :bar) { }
42
+ hooks = instance.send(type, :foo => :bar) {}
43
43
  hook = hooks.first
44
44
  instance.hooks[type][:each].should include(hook)
45
45
  end
46
46
 
47
47
  it "raises an error if only metadata symbols are given as arguments" do
48
- expect { instance.send(type, :foo, :bar) { } }.to raise_error(ArgumentError)
48
+ expect { instance.send(type, :foo, :bar) {} }.to raise_error(ArgumentError)
49
49
  end
50
50
  end
51
51
  end
@@ -63,7 +63,7 @@ module RSpec::Core
63
63
  describe "##{type}(#{scope.inspect})" do
64
64
  let(:instance) { HooksHost.new }
65
65
  let!(:hook) do
66
- hooks = instance.send(type, scope) { }
66
+ hooks = instance.send(type, scope) {}
67
67
  hooks.first
68
68
  end
69
69
 
@@ -119,6 +119,7 @@ module RSpec::Core
119
119
  def yielder
120
120
  yield
121
121
  end
122
+
122
123
  around do |example|
123
124
  yielder { example.run }
124
125
  end
@@ -130,12 +131,118 @@ module RSpec::Core
130
131
  examples.should have(1).example
131
132
  end
132
133
  end
134
+ end
135
+
136
+ [:all, :each].each do |scope|
137
+ describe "prepend_before(#{scope})" do
138
+ it "adds to the front of the list of before(:#{scope}) hooks" do
139
+ messages = []
140
+
141
+ RSpec.configure { |config| config.before(scope) { messages << "config 3" } }
142
+ RSpec.configure { |config| config.prepend_before(scope) { messages << "config 2" } }
143
+ RSpec.configure { |config| config.before(scope) { messages << "config 4" } }
144
+ RSpec.configure { |config| config.prepend_before(scope) { messages << "config 1" } }
145
+
146
+ group = ExampleGroup.describe { example {} }
147
+ group.before(scope) { messages << "group 3" }
148
+ group.prepend_before(scope) { messages << "group 2" }
149
+ group.before(scope) { messages << "group 4" }
150
+ group.prepend_before(scope) { messages << "group 1" }
151
+
152
+ group.run
153
+
154
+ messages.should eq([
155
+ 'group 1',
156
+ 'group 2',
157
+ 'config 1',
158
+ 'config 2',
159
+ 'config 3',
160
+ 'config 4',
161
+ 'group 3',
162
+ 'group 4'
163
+ ])
164
+ end
165
+ end
166
+
167
+ describe "append_before(#{scope})" do
168
+ it "adds to the back of the list of before(:#{scope}) hooks (same as `before`)" do
169
+ messages = []
170
+
171
+ RSpec.configure { |config| config.before(scope) { messages << "config 1" } }
172
+ RSpec.configure { |config| config.append_before(scope) { messages << "config 2" } }
173
+ RSpec.configure { |config| config.before(scope) { messages << "config 3" } }
174
+
175
+ group = ExampleGroup.describe { example {} }
176
+ group.before(scope) { messages << "group 1" }
177
+ group.append_before(scope) { messages << "group 2" }
178
+ group.before(scope) { messages << "group 3" }
179
+
180
+ group.run
181
+
182
+ messages.should eq([
183
+ 'config 1',
184
+ 'config 2',
185
+ 'config 3',
186
+ 'group 1',
187
+ 'group 2',
188
+ 'group 3'
189
+ ])
190
+ end
191
+ end
192
+
193
+ describe "prepend_after(#{scope})" do
194
+ it "adds to the front of the list of after(:#{scope}) hooks (same as `after`)" do
195
+ messages = []
196
+
197
+ RSpec.configure { |config| config.after(scope) { messages << "config 3" } }
198
+ RSpec.configure { |config| config.prepend_after(scope) { messages << "config 2" } }
199
+ RSpec.configure { |config| config.after(scope) { messages << "config 1" } }
200
+
201
+ group = ExampleGroup.describe { example {} }
202
+ group.after(scope) { messages << "group 3" }
203
+ group.prepend_after(scope) { messages << "group 2" }
204
+ group.after(scope) { messages << "group 1" }
205
+
206
+ group.run
207
+
208
+ messages.should eq([
209
+ 'group 1',
210
+ 'group 2',
211
+ 'group 3',
212
+ 'config 1',
213
+ 'config 2',
214
+ 'config 3'
215
+ ])
216
+ end
217
+ end
218
+
219
+ describe "append_after(#{scope})" do
220
+ it "adds to the back of the list of after(:#{scope}) hooks" do
221
+ messages = []
222
+
223
+ RSpec.configure { |config| config.after(scope) { messages << "config 2" } }
224
+ RSpec.configure { |config| config.append_after(scope) { messages << "config 3" } }
225
+ RSpec.configure { |config| config.after(scope) { messages << "config 1" } }
226
+ RSpec.configure { |config| config.append_after(scope) { messages << "config 4" } }
227
+
228
+ group = ExampleGroup.describe { example {} }
229
+ group.after(scope) { messages << "group 2" }
230
+ group.append_after(scope) { messages << "group 3" }
231
+ group.after(scope) { messages << "group 1" }
232
+ group.append_after(scope) { messages << "group 4" }
233
+
234
+ group.run
133
235
 
134
- describe Hooks::Hook do
135
- it "requires a block" do
136
- lambda {
137
- Hooks::BeforeHook.new :foo => :bar
138
- }.should raise_error("no block given for before hook")
236
+ messages.should eq([
237
+ 'group 1',
238
+ 'group 2',
239
+ 'config 1',
240
+ 'config 2',
241
+ 'config 3',
242
+ 'config 4',
243
+ 'group 3',
244
+ 'group 4'
245
+ ])
139
246
  end
140
247
  end
141
248
  end
@@ -118,6 +118,10 @@ module RSpec
118
118
  end
119
119
  end
120
120
 
121
+ it "matches a proc with no arguments that evaluates to true" do
122
+ example_metadata.filter_applies?(:if, lambda { true }).should be_true
123
+ end
124
+
121
125
  it "matches a proc that evaluates to true" do
122
126
  example_metadata.filter_applies?(:if, lambda { |v| v }).should be_true
123
127
  end
@@ -131,6 +135,12 @@ module RSpec
131
135
  example_metadata.filter_applies?(:foo, lambda { |v, m| m == example_metadata }).should be_true
132
136
  end
133
137
 
138
+ it "raises an error when the proc has an incorrect arity" do
139
+ expect {
140
+ example_metadata.filter_applies?(:if, lambda { |a,b,c| true })
141
+ }.to raise_error(ArgumentError)
142
+ end
143
+
134
144
  context "with an Array" do
135
145
  let(:metadata_with_array) {
136
146
  group_metadata.for_example('example_with_array', :tag => [:one, 2, 'three', /four/])
@@ -188,7 +198,7 @@ module RSpec
188
198
  end
189
199
 
190
200
  it "extracts file path from caller" do
191
- mfe[:file_path].should eq(__FILE__)
201
+ mfe[:file_path].should eq(relative_path(__FILE__))
192
202
  end
193
203
 
194
204
  it "extracts line number from caller" do
@@ -196,7 +206,7 @@ module RSpec
196
206
  end
197
207
 
198
208
  it "extracts location from caller" do
199
- mfe[:location].should eq("#{__FILE__}:#{line_number}")
209
+ mfe[:location].should eq("#{relative_path(__FILE__)}:#{line_number}")
200
210
  end
201
211
 
202
212
  it "uses :caller if passed as an option" do
@@ -397,7 +407,7 @@ module RSpec
397
407
  "./lib/rspec/core/foo.rb",
398
408
  "#{__FILE__}:#{__LINE__}"
399
409
  ])
400
- m[:example_group][:file_path].should eq(__FILE__)
410
+ m[:example_group][:file_path].should eq(relative_path(__FILE__))
401
411
  end
402
412
  end
403
413
 
@@ -70,9 +70,10 @@ describe "an example" do
70
70
  end
71
71
  example = group.examples.last
72
72
  example.run(group.new, stub.as_null_object)
73
- example.description.should be_empty
73
+ example.description.should match(/example at/)
74
74
  end
75
75
  end
76
+
76
77
  context "after another example with some assertion" do
77
78
  it "does not show any message" do
78
79
  group = RSpec::Core::ExampleGroup.describe('group') do
@@ -85,7 +86,7 @@ describe "an example" do
85
86
  end
86
87
  example = group.examples.last
87
88
  example.run(group.new, stub.as_null_object)
88
- example.description.should be_empty
89
+ example.description.should match(/example at/)
89
90
  end
90
91
  end
91
92
  end