rspec-core 2.10.1 → 2.11.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 (37) hide show
  1. data/Changelog.md +35 -2
  2. data/README.md +14 -13
  3. data/features/command_line/example_name_option.feature +15 -0
  4. data/features/helper_methods/modules.feature +3 -3
  5. data/lib/rspec/core.rb +6 -2
  6. data/lib/rspec/core/configuration.rb +61 -26
  7. data/lib/rspec/core/configuration_options.rb +5 -1
  8. data/lib/rspec/core/deprecation.rb +0 -15
  9. data/lib/rspec/core/drb_command_line.rb +3 -0
  10. data/lib/rspec/core/drb_options.rb +3 -1
  11. data/lib/rspec/core/dsl.rb +4 -2
  12. data/lib/rspec/core/example.rb +85 -23
  13. data/lib/rspec/core/example_group.rb +103 -78
  14. data/lib/rspec/core/hooks.rb +68 -33
  15. data/lib/rspec/core/let.rb +0 -1
  16. data/lib/rspec/core/mocking/with_mocha.rb +10 -4
  17. data/lib/rspec/core/option_parser.rb +3 -2
  18. data/lib/rspec/core/project_initializer.rb +7 -1
  19. data/lib/rspec/core/runner.rb +2 -2
  20. data/lib/rspec/core/shared_context.rb +2 -2
  21. data/lib/rspec/core/shared_example_group.rb +38 -14
  22. data/lib/rspec/core/subject.rb +67 -52
  23. data/lib/rspec/core/version.rb +1 -1
  24. data/spec/rspec/core/command_line_spec.rb +68 -126
  25. data/spec/rspec/core/configuration_options_spec.rb +20 -4
  26. data/spec/rspec/core/configuration_spec.rb +61 -21
  27. data/spec/rspec/core/drb_command_line_spec.rb +1 -0
  28. data/spec/rspec/core/drb_options_spec.rb +1 -0
  29. data/spec/rspec/core/dsl_spec.rb +17 -0
  30. data/spec/rspec/core/example_group_spec.rb +19 -11
  31. data/spec/rspec/core/example_spec.rb +34 -0
  32. data/spec/rspec/core/option_parser_spec.rb +2 -1
  33. data/spec/rspec/core/shared_example_group_spec.rb +9 -9
  34. data/spec/rspec/core/subject_spec.rb +14 -0
  35. data/spec/rspec/core_spec.rb +18 -8
  36. data/spec/spec_helper.rb +1 -2
  37. metadata +7 -5
@@ -95,6 +95,22 @@ describe RSpec::Core::ConfigurationOptions, :fakefs do
95
95
  config.should_receive(:debug=).with(true)
96
96
  opts.configure(config)
97
97
  end
98
+
99
+ it "merges --require specified by multiple configuration sources" do
100
+ ENV['SPEC_OPTS'] = "--require file_from_env"
101
+ opts = config_options_object(*%w[--require file_from_opts])
102
+ config = RSpec::Core::Configuration.new
103
+ config.should_receive(:requires=).with(["file_from_opts", "file_from_env"])
104
+ opts.configure(config)
105
+ end
106
+
107
+ it "merges --I specified by multiple configuration sources" do
108
+ ENV['SPEC_OPTS'] = "-I dir_from_env"
109
+ opts = config_options_object(*%w[-I dir_from_opts])
110
+ config = RSpec::Core::Configuration.new
111
+ config.should_receive(:libs=).with(["dir_from_opts", "dir_from_env"])
112
+ opts.configure(config)
113
+ end
98
114
  end
99
115
 
100
116
  describe "-c, --color, and --colour" do
@@ -170,8 +186,8 @@ describe RSpec::Core::ConfigurationOptions, :fakefs do
170
186
 
171
187
  describe "--example" do
172
188
  it "sets :full_description" do
173
- parse_options('--example','foo').should include(:full_description => /foo/)
174
- parse_options('-e','bar').should include(:full_description => /bar/)
189
+ parse_options('--example','foo').should include(:full_description => [/foo/])
190
+ parse_options('-e','bar').should include(:full_description => [/bar/])
175
191
  end
176
192
  end
177
193
 
@@ -321,7 +337,7 @@ describe RSpec::Core::ConfigurationOptions, :fakefs do
321
337
  options[:color].should be_true
322
338
  options[:line_numbers].should eq(["37"])
323
339
  options[:debug].should be_true
324
- options[:full_description].should eq(/foo\ bar/)
340
+ options[:full_description].should eq([/foo\ bar/])
325
341
  options[:drb].should be_true
326
342
  end
327
343
 
@@ -354,7 +370,7 @@ describe RSpec::Core::ConfigurationOptions, :fakefs do
354
370
  it "parses -e 'full spec description'" do
355
371
  File.open("./custom.opts", "w") {|f| f << "-e 'The quick brown fox jumps over the lazy dog'"}
356
372
  options = parse_options("-O", "./custom.opts")
357
- options[:full_description].should == /The\ quick\ brown\ fox\ jumps\ over\ the\ lazy\ dog/
373
+ options[:full_description].should eq([/The\ quick\ brown\ fox\ jumps\ over\ the\ lazy\ dog/])
358
374
  end
359
375
  end
360
376
  end
@@ -64,10 +64,37 @@ module RSpec::Core
64
64
  end
65
65
  end
66
66
 
67
+ shared_examples "a configurable framework adapter" do |m|
68
+ it "yields a config object if the framework_module supports it" do
69
+ custom_config = Struct.new(:custom_setting).new
70
+ mod = Module.new
71
+ mod.stub(:configuration => custom_config)
72
+
73
+ config.send m, mod do |mod_config|
74
+ mod_config.custom_setting = true
75
+ end
76
+
77
+ custom_config.custom_setting.should be_true
78
+ end
79
+
80
+ it "raises if framework module doesn't support configuration" do
81
+ mod = Module.new
82
+
83
+ lambda do
84
+ config.send m, mod do |mod_config|
85
+ end
86
+ end.should raise_error /must respond to `configuration`/
87
+ end
88
+ end
89
+
67
90
  describe "#mock_with" do
91
+ before { config.stub(:require) }
92
+
93
+ it_behaves_like "a configurable framework adapter", :mock_with
94
+
68
95
  [:rspec, :mocha, :rr, :flexmock].each do |framework|
69
96
  context "with #{framework}" do
70
- it "requires the adapter for #{framework.inspect}" do
97
+ it "requires the adapter for #{framework}" do
71
98
  config.should_receive(:require).with("rspec/core/mocking/with_#{framework}")
72
99
  config.mock_with framework
73
100
  end
@@ -76,7 +103,6 @@ module RSpec::Core
76
103
 
77
104
  context "with a module" do
78
105
  it "sets the mock_framework_adapter to that module" do
79
- config.stub(:require)
80
106
  mod = Module.new
81
107
  config.mock_with mod
82
108
  config.mock_framework.should eq(mod)
@@ -89,8 +115,6 @@ module RSpec::Core
89
115
  end
90
116
 
91
117
  context 'when there are already some example groups defined' do
92
- before(:each) { config.stub(:require) }
93
-
94
118
  it 'raises an error since this setting must be applied before any groups are defined' do
95
119
  RSpec.world.stub(:example_groups).and_return([double.as_null_object])
96
120
  expect {
@@ -129,16 +153,14 @@ module RSpec::Core
129
153
  end
130
154
 
131
155
  describe "#expect_with" do
132
- before(:each) do
133
- # we need to prevent stdlib from being required because it defines a
134
- # `pass` method that conflicts with our `pass` matcher.
135
- config.stub(:require)
136
- end
156
+ before { config.stub(:require) }
157
+
158
+ it_behaves_like "a configurable framework adapter", :expect_with
137
159
 
138
160
  [
139
161
  [:rspec, 'rspec/expectations'],
140
162
  [:stdlib, 'test/unit/assertions']
141
- ].each do |(framework, required_file)|
163
+ ].each do |framework, required_file|
142
164
  context "with #{framework}" do
143
165
  it "requires #{required_file}" do
144
166
  config.should_receive(:require).with(required_file)
@@ -147,6 +169,19 @@ module RSpec::Core
147
169
  end
148
170
  end
149
171
 
172
+ it "supports multiple calls" do
173
+ config.expect_with :rspec
174
+ config.expect_with :stdlib
175
+ config.expectation_frameworks.should eq [RSpec::Matchers, Test::Unit::Assertions]
176
+ end
177
+
178
+ it "raises if block given with multiple args" do
179
+ lambda do
180
+ config.expect_with :rspec, :stdlib do |mod_config|
181
+ end
182
+ end.should raise_error /expect_with only accepts/
183
+ end
184
+
150
185
  it "raises ArgumentError if framework is not supported" do
151
186
  expect do
152
187
  config.expect_with :not_supported
@@ -178,11 +213,7 @@ module RSpec::Core
178
213
  end
179
214
 
180
215
  describe "#expecting_with_rspec?" do
181
- before(:each) do
182
- # prevent minitest assertions from being required and included,
183
- # as that causes problems in some of our specs.
184
- config.stub(:require)
185
- end
216
+ before { config.stub(:require) }
186
217
 
187
218
  it "returns false by default" do
188
219
  config.should_not be_expecting_with_rspec
@@ -215,13 +246,13 @@ module RSpec::Core
215
246
  config.files_to_run.should eq([ "spec/rspec/core/resources/a_bar.rb"])
216
247
  end
217
248
 
218
- it "prevents repitition of dir when start of the pattern" do
249
+ it "prevents repetition of dir when start of the pattern" do
219
250
  config.pattern = "spec/**/a_spec.rb"
220
251
  config.files_or_directories_to_run = "spec"
221
252
  config.files_to_run.should eq(["spec/rspec/core/resources/a_spec.rb"])
222
253
  end
223
254
 
224
- it "does not prevent repitition of dir when later of the pattern" do
255
+ it "does not prevent repetition of dir when later of the pattern" do
225
256
  config.pattern = "rspec/**/a_spec.rb"
226
257
  config.files_or_directories_to_run = "spec"
227
258
  config.files_to_run.should eq(["spec/rspec/core/resources/a_spec.rb"])
@@ -265,10 +296,14 @@ module RSpec::Core
265
296
  config.files_to_run.should eq([ "spec/rspec/core/resources/a_spec.rb"])
266
297
  end
267
298
 
268
- it "loads files in Windows" do
269
- file = "C:\\path\\to\\project\\spec\\sub\\foo_spec.rb"
270
- config.files_or_directories_to_run = file
271
- config.files_to_run.should eq([file])
299
+ it "loads files in Windows", :if => RSpec.windows_os? do
300
+ config.files_or_directories_to_run = "C:\\path\\to\\project\\spec\\sub\\foo_spec.rb"
301
+ config.files_to_run.should eq([ "C:/path/to/project/spec/sub/foo_spec.rb"])
302
+ end
303
+
304
+ it "loads files in Windows when directory is specified", :if => RSpec.windows_os? do
305
+ config.files_or_directories_to_run = "spec\\rspec\\core\\resources"
306
+ config.files_to_run.should eq([ "spec/rspec/core/resources/a_spec.rb"])
272
307
  end
273
308
  end
274
309
 
@@ -376,6 +411,11 @@ module RSpec::Core
376
411
  config.filter.should eq({:full_description => /foo/})
377
412
  end
378
413
 
414
+ it "assigns the example names as the filter on description if description is an array" do
415
+ config.full_description = [ "foo", "bar" ]
416
+ config.filter.should eq({:full_description => Regexp.union(/foo/, /bar/)})
417
+ end
418
+
379
419
  describe "#default_path" do
380
420
  it 'defaults to "spec"' do
381
421
  config.default_path.should eq('spec')
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require 'rspec/core/drb_command_line'
2
3
 
3
4
  describe "::DRbCommandLine", :type => :drb, :unless => RUBY_PLATFORM == 'java' do
4
5
  let(:config) { RSpec::Core::Configuration.new }
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require 'rspec/core/drb_options'
2
3
 
3
4
  describe RSpec::Core::DrbOptions, :fakefs do
4
5
  include ConfigOptionsHelper
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ main = self
4
+ describe "The describe method" do
5
+ it 'is available on the main object' do
6
+ main.should respond_to(:describe)
7
+ end
8
+
9
+ it 'is available on modules (so example groups can be nested inside them)' do
10
+ Module.new.should respond_to(:describe)
11
+ end
12
+
13
+ it 'is not available on other types of objects' do
14
+ Object.new.should_not respond_to(:describe)
15
+ end
16
+ end
17
+
@@ -359,15 +359,14 @@ module RSpec::Core
359
359
 
360
360
  [:focus, :focused].each do |example_alias|
361
361
  describe "##{example_alias}" do
362
- let(:group) { ExampleGroup.describe }
363
- subject { group.send example_alias, "a focused example" }
362
+ let(:focused_example) { ExampleGroup.describe.send example_alias, "a focused example" }
364
363
 
365
364
  it 'defines an example that can be filtered with :focused => true' do
366
- subject.metadata.should include(:focused => true)
365
+ focused_example.metadata[:focused].should be_true
367
366
  end
368
367
 
369
368
  it 'defines an example that can be filtered with :focus => true' do
370
- subject.metadata.should include(:focus => true)
369
+ focused_example.metadata[:focus].should be_true
371
370
  end
372
371
  end
373
372
  end
@@ -866,7 +865,7 @@ module RSpec::Core
866
865
 
867
866
  context "with all examples passing" do
868
867
  it "returns true" do
869
- group = describe("something") do
868
+ group = RSpec::Core::ExampleGroup.describe("something") do
870
869
  it "does something" do
871
870
  # pass
872
871
  end
@@ -883,7 +882,7 @@ module RSpec::Core
883
882
 
884
883
  context "with top level example failing" do
885
884
  it "returns false" do
886
- group = describe("something") do
885
+ group = RSpec::Core::ExampleGroup.describe("something") do
887
886
  it "does something (wrong - fail)" do
888
887
  raise "fail"
889
888
  end
@@ -900,7 +899,7 @@ module RSpec::Core
900
899
 
901
900
  context "with nested example failing" do
902
901
  it "returns true" do
903
- group = describe("something") do
902
+ group = RSpec::Core::ExampleGroup.describe("something") do
904
903
  it "does something" do
905
904
  # pass
906
905
  end
@@ -971,10 +970,19 @@ module RSpec::Core
971
970
  eval_count.should eq(1)
972
971
  end
973
972
 
974
- it "warns the user that blocks are not supported when given a block" do
975
- group = ExampleGroup.describe
976
- group.should_receive(:warn).with(/blocks not supported for #{name}/)
977
- group.send(name, "named this with block") {}
973
+ it "evals the block when given" do
974
+ key = "#{__FILE__}:#{__LINE__}"
975
+ shared_examples(key) do
976
+ it("does something") do
977
+ foo.should eq("bar")
978
+ end
979
+ end
980
+ group = ExampleGroup.describe do
981
+ send name, key do
982
+ def foo; "bar"; end
983
+ end
984
+ end
985
+ group.run.should be_true
978
986
  end
979
987
  end
980
988
  end
@@ -258,6 +258,40 @@ describe RSpec::Core::Example, :parent_metadata => 'sample' do
258
258
  group.run.should be_true
259
259
  end
260
260
  end
261
+
262
+ context "when the example and an around hook raise errors" do
263
+ it "prints the around hook error rather than silencing it" do
264
+ group = RSpec::Core::ExampleGroup.describe do
265
+ around(:each) { |e| e.run; raise "around" }
266
+ example("e") { raise "example" }
267
+ end
268
+
269
+ reported_msg = nil
270
+ # We can't use should_receive(:message).with(/.../) here,
271
+ # because if that fails, it would fail within our example-under-test,
272
+ # and since there's already two errors, it would just be reported again.
273
+ RSpec.configuration.reporter.stub(:message) { |msg| reported_msg = msg }
274
+ group.run
275
+ reported_msg.should =~ /An error occurred in an around.* hook/i
276
+ end
277
+ end
278
+
279
+ context "when the example and an after hook raise errors" do
280
+ it "prints the after hook error rather than silencing it" do
281
+ group = RSpec::Core::ExampleGroup.describe do
282
+ after(:each) { raise "after" }
283
+ example("e") { raise "example" }
284
+ end
285
+
286
+ reported_msg = nil
287
+ # We can't use should_receive(:message).with(/.../) here,
288
+ # because if that fails, it would fail within our example-under-test,
289
+ # and since there's already two errors, it would just be reported again.
290
+ RSpec.configuration.reporter.stub(:message) { |msg| reported_msg = msg }
291
+ group.run
292
+ reported_msg.should =~ /An error occurred in an after.* hook/i
293
+ end
294
+ end
261
295
  end
262
296
 
263
297
  describe "#pending" do
@@ -68,7 +68,8 @@ module RSpec::Core
68
68
  describe option do
69
69
  it "escapes the arg" do
70
70
  options = Parser.parse!([option, "this (and that)"])
71
- "this (and that)".should match(options[:full_description])
71
+ options[:full_description].length.should == 1
72
+ "this (and that)".should match(options[:full_description].first)
72
73
  end
73
74
  end
74
75
  end
@@ -6,17 +6,17 @@ module RSpec::Core
6
6
  ExampleModule = Module.new
7
7
  ExampleClass = Class.new
8
8
 
9
- %w[share_examples_for shared_examples_for].each do |method_name|
10
- describe method_name do
9
+ %w[share_examples_for shared_examples_for shared_examples shared_context].each do |shared_method_name|
10
+ describe shared_method_name do
11
11
  it "is exposed to the global namespace" do
12
- Kernel.should respond_to(method_name)
12
+ Kernel.should respond_to(shared_method_name)
13
13
  end
14
14
 
15
15
  it "raises an ArgumentError when adding a second shared example group with the same name" do
16
16
  group = ExampleGroup.describe('example group')
17
- group.send(method_name, 'shared group') {}
17
+ group.send(shared_method_name, 'shared group') {}
18
18
  lambda do
19
- group.send(method_name, 'shared group') {}
19
+ group.send(shared_method_name, 'shared group') {}
20
20
  end.should raise_error(ArgumentError, "Shared example group 'shared group' already exists")
21
21
  end
22
22
 
@@ -26,7 +26,7 @@ module RSpec::Core
26
26
  it "captures the given #{type} and block in the World's collection of shared example groups" do
27
27
  implementation = lambda {}
28
28
  RSpec.world.shared_example_groups.should_receive(:[]=).with(object, implementation)
29
- send(method_name, object, &implementation)
29
+ send(shared_method_name, object, &implementation)
30
30
  end
31
31
  end
32
32
  end
@@ -34,7 +34,7 @@ module RSpec::Core
34
34
  context "given a hash" do
35
35
  it "delegates extend on configuration" do
36
36
  implementation = Proc.new { def bar; 'bar'; end }
37
- send(method_name, :foo => :bar, &implementation)
37
+ send(shared_method_name, :foo => :bar, &implementation)
38
38
  a = RSpec.configuration.include_or_extend_modules.first
39
39
  a[0].should eq(:extend)
40
40
  Class.new.extend(a[1]).new.bar.should eq('bar')
@@ -46,12 +46,12 @@ module RSpec::Core
46
46
  it "captures the given string and block in the World's collection of shared example groups" do
47
47
  implementation = lambda {}
48
48
  RSpec.world.shared_example_groups.should_receive(:[]=).with("name", implementation)
49
- send(method_name, "name", :foo => :bar, &implementation)
49
+ send(shared_method_name, "name", :foo => :bar, &implementation)
50
50
  end
51
51
 
52
52
  it "delegates extend on configuration" do
53
53
  implementation = Proc.new { def bar; 'bar'; end }
54
- send(method_name, "name", :foo => :bar, &implementation)
54
+ send(shared_method_name, "name", :foo => :bar, &implementation)
55
55
  a = RSpec.configuration.include_or_extend_modules.first
56
56
  a[0].should eq(:extend)
57
57
  Class.new.extend(a[1]).new.bar.should eq('bar')
@@ -78,6 +78,20 @@ module RSpec::Core
78
78
  doubly_nested_group.subject.call.should eq([4,5,6])
79
79
  end
80
80
  end
81
+
82
+ describe "with a name" do
83
+ it "defines a method that returns the memoized subject" do
84
+ group = ExampleGroup.describe do
85
+ subject(:list) { [1,2,3] }
86
+ example do
87
+ list.should equal(list)
88
+ subject.should equal(subject)
89
+ subject.should equal(list)
90
+ end
91
+ end
92
+ group.run.should be_true
93
+ end
94
+ end
81
95
  end
82
96
 
83
97
  context "using 'self' as an explicit subject" do
@@ -1,25 +1,35 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe RSpec::Core do
4
-
5
- describe "#configuration" do
3
+ describe RSpec do
4
+ describe "::configuration" do
6
5
  it "returns the same object every time" do
7
6
  RSpec.configuration.should equal(RSpec.configuration)
8
7
  end
9
8
  end
10
9
 
11
- describe "#configure" do
10
+ describe "::configure" do
12
11
  it "yields the current configuration" do
13
12
  RSpec.configure do |config|
14
- config.should eq(RSpec::configuration)
13
+ config.should equal(RSpec::configuration)
15
14
  end
16
15
  end
17
16
  end
18
17
 
19
- describe "#world" do
20
- it "returns the RSpec::Core::World instance the current run is using" do
21
- RSpec.world.should be_instance_of(RSpec::Core::World)
18
+ describe "::world" do
19
+ it "returns the same object every time" do
20
+ RSpec.world.should equal(RSpec.world)
22
21
  end
23
22
  end
24
23
 
24
+ describe "::reset" do
25
+ it "resets the configuration and world objects" do
26
+ config_before_reset = RSpec.configuration
27
+ world_before_reset = RSpec.world
28
+
29
+ RSpec.reset
30
+
31
+ RSpec.configuration.should_not equal(config_before_reset)
32
+ RSpec.world.should_not equal(world_before_reset)
33
+ end
34
+ end
25
35
  end