rspec-core 2.10.1 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
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