rspec-core 2.9.0 → 2.10.0

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