rspec-core 2.14.8 → 2.99.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +8 -8
  2. data/Changelog.md +54 -8
  3. data/features/command_line/order.feature +5 -8
  4. data/features/configuration/custom_settings.feature +10 -10
  5. data/features/configuration/deprecation_stream.feature +3 -3
  6. data/features/configuration/read_options_from_file.feature +1 -1
  7. data/features/example_groups/shared_examples.feature +2 -2
  8. data/features/hooks/around_hooks.feature +1 -1
  9. data/features/metadata/current_example.feature +43 -4
  10. data/features/metadata/user_defined.feature +12 -12
  11. data/lib/autotest/rspec2.rb +60 -56
  12. data/lib/rspec/core.rb +40 -2
  13. data/lib/rspec/core/caller_filter.rb +55 -0
  14. data/lib/rspec/core/command_line.rb +2 -2
  15. data/lib/rspec/core/configuration.rb +201 -13
  16. data/lib/rspec/core/deprecation.rb +2 -7
  17. data/lib/rspec/core/example.rb +5 -8
  18. data/lib/rspec/core/example_group.rb +101 -17
  19. data/lib/rspec/core/filter_manager.rb +2 -2
  20. data/lib/rspec/core/formatters/deprecation_formatter.rb +173 -15
  21. data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -12
  22. data/lib/rspec/core/hooks.rb +1 -1
  23. data/lib/rspec/core/memoized_helpers.rb +49 -17
  24. data/lib/rspec/core/metadata.rb +1 -1
  25. data/lib/rspec/core/option_parser.rb +8 -3
  26. data/lib/rspec/core/pending.rb +14 -10
  27. data/lib/rspec/core/rake_task.rb +30 -6
  28. data/lib/rspec/core/runner.rb +9 -0
  29. data/lib/rspec/core/shared_example_group.rb +11 -9
  30. data/lib/rspec/core/shared_example_group/collection.rb +3 -1
  31. data/lib/rspec/core/version.rb +1 -2
  32. data/spec/command_line/order_spec.rb +4 -4
  33. data/spec/rspec/core/backtrace_cleaner_spec.rb +10 -10
  34. data/spec/rspec/core/caller_filter_spec.rb +58 -0
  35. data/spec/rspec/core/command_line_spec.rb +1 -0
  36. data/spec/rspec/core/configuration_options_spec.rb +6 -6
  37. data/spec/rspec/core/configuration_spec.rb +285 -52
  38. data/spec/rspec/core/deprecation_spec.rb +10 -29
  39. data/spec/rspec/core/deprecations_spec.rb +0 -14
  40. data/spec/rspec/core/example_group_spec.rb +74 -56
  41. data/spec/rspec/core/example_spec.rb +54 -17
  42. data/spec/rspec/core/filter_manager_spec.rb +2 -2
  43. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +156 -52
  44. data/spec/rspec/core/formatters/html_formatter_spec.rb +1 -1
  45. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -2
  46. data/spec/rspec/core/hooks_spec.rb +2 -0
  47. data/spec/rspec/core/memoized_helpers_spec.rb +154 -113
  48. data/spec/rspec/core/metadata_spec.rb +25 -25
  49. data/spec/rspec/core/option_parser_spec.rb +19 -1
  50. data/spec/rspec/core/project_initializer_spec.rb +4 -4
  51. data/spec/rspec/core/rake_task_spec.rb +25 -4
  52. data/spec/rspec/core/shared_context_spec.rb +4 -4
  53. data/spec/rspec/core/shared_example_group_spec.rb +1 -1
  54. data/spec/rspec/core_spec.rb +36 -2
  55. data/spec/spec_helper.rb +3 -0
  56. data/spec/support/helper_methods.rb +16 -1
  57. data/spec/support/shared_example_groups.rb +1 -0
  58. data/spec/support/silence_dsl_deprecations.rb +32 -0
  59. metadata +10 -7
  60. data/spec/rspec/core/formatters/text_mate_formatted-2.1.0.html +0 -425
@@ -165,7 +165,7 @@ module RSpec::Core
165
165
  describe "#inclusions#description" do
166
166
  it 'cleans up the description' do
167
167
  project_dir = File.expand_path('.')
168
- expect(lambda { }.inspect).to include(project_dir)
168
+ expect(lambda { }.inspect).to include(project_dir) unless defined?(JRUBY_VERSION) && JRUBY_VERSION == '1.7.4'
169
169
  expect(lambda { }.inspect).to include(' (lambda)') if RUBY_VERSION > '1.9'
170
170
  expect(lambda { }.inspect).to include('0x')
171
171
 
@@ -181,7 +181,7 @@ module RSpec::Core
181
181
  describe "#exclusions#description" do
182
182
  it 'cleans up the description' do
183
183
  project_dir = File.expand_path('.')
184
- expect(lambda { }.inspect).to include(project_dir)
184
+ expect(lambda { }.inspect).to include(project_dir) unless defined?(JRUBY_VERSION) && JRUBY_VERSION == '1.7.4'
185
185
  expect(lambda { }.inspect).to include(' (lambda)') if RUBY_VERSION > '1.9'
186
186
  expect(lambda { }.inspect).to include('0x')
187
187
 
@@ -6,7 +6,7 @@ module RSpec::Core::Formatters
6
6
  describe DeprecationFormatter do
7
7
  let(:deprecation_stream) { StringIO.new }
8
8
  let(:summary_stream) { StringIO.new }
9
- let(:formatter) { DeprecationFormatter.new deprecation_stream, summary_stream }
9
+ let(:formatter) { DeprecationFormatter.new(deprecation_stream, summary_stream) }
10
10
 
11
11
  def with_start_defined_on_kernel
12
12
  return yield if ::Kernel.method_defined?(:start)
@@ -27,69 +27,173 @@ module RSpec::Core::Formatters
27
27
  end
28
28
 
29
29
  describe "#deprecation" do
30
- it "includes the method" do
31
- formatter.deprecation(:deprecated => "i_am_deprecated")
32
- deprecation_stream.rewind
33
- expect(deprecation_stream.read).to match(/i_am_deprecated is deprecated/)
34
- end
30
+ let(:formatter) { DeprecationFormatter.new(deprecation_stream, summary_stream) }
31
+ let(:summary_stream) { StringIO.new }
35
32
 
36
- it "includes the replacement" do
37
- formatter.deprecation(:replacement => "use_me")
38
- deprecation_stream.rewind
39
- expect(deprecation_stream.read).to match(/Use use_me instead/)
40
- end
33
+ context "with a File deprecation_stream" do
34
+ let(:deprecation_stream) { File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w+") }
35
+
36
+ it "prints a message if provided, ignoring other data" do
37
+ formatter.deprecation(:message => "this message", :deprecated => "x", :replacement => "y", :call_site => "z")
38
+ deprecation_stream.rewind
39
+ expect(deprecation_stream.read).to eq "this message\n"
40
+ end
41
41
 
42
- it "includes the call site if provided" do
43
- formatter.deprecation(:call_site => "somewhere")
44
- deprecation_stream.rewind
45
- expect(deprecation_stream.read).to match(/Called from somewhere/)
42
+ it "includes the method" do
43
+ formatter.deprecation(:deprecated => "i_am_deprecated")
44
+ deprecation_stream.rewind
45
+ expect(deprecation_stream.read).to match(/i_am_deprecated is deprecated/)
46
+ end
47
+
48
+ it "includes the replacement" do
49
+ formatter.deprecation(:replacement => "use_me")
50
+ deprecation_stream.rewind
51
+ expect(deprecation_stream.read).to match(/Use use_me instead/)
52
+ end
53
+
54
+ it "includes the call site if provided" do
55
+ formatter.deprecation(:call_site => "somewhere")
56
+ deprecation_stream.rewind
57
+ expect(deprecation_stream.read).to match(/Called from somewhere/)
58
+ end
46
59
  end
47
60
 
48
- it "prints a message if provided, ignoring other data" do
49
- formatter.deprecation(:message => "this message", :deprecated => "x", :replacement => "y", :call_site => "z")
50
- deprecation_stream.rewind
51
- expect(deprecation_stream.read).to eq "this message"
61
+ context "with an IO deprecation stream" do
62
+ let(:deprecation_stream) { StringIO.new }
63
+
64
+ it "prints nothing" do
65
+ 5.times { formatter.deprecation(:deprecated => 'i_am_deprecated') }
66
+ expect(deprecation_stream.string).to eq ""
67
+ end
52
68
  end
53
69
  end
54
70
 
55
71
  describe "#deprecation_summary" do
56
- it "is printed when deprecations go to a file" do
57
- file = File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w")
58
- summary_stream = StringIO.new
59
- formatter = DeprecationFormatter.new file, summary_stream
60
- formatter.deprecation(:deprecated => 'i_am_deprecated')
61
- formatter.deprecation_summary
62
- summary_stream.rewind
63
- expect(summary_stream.read).to match(/1 deprecation logged to .*deprecation_summary_example_output/)
64
- end
72
+ let(:formatter) { DeprecationFormatter.new(deprecation_stream, summary_stream) }
73
+ let(:summary_stream) { StringIO.new }
65
74
 
66
- it "pluralizes for more than one deprecation" do
67
- file = File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w")
68
- summary_stream = StringIO.new
69
- formatter = DeprecationFormatter.new file, summary_stream
70
- formatter.deprecation(:deprecated => 'i_am_deprecated')
71
- formatter.deprecation(:deprecated => 'i_am_deprecated_also')
72
- formatter.deprecation_summary
73
- summary_stream.rewind
74
- expect(summary_stream.read).to match(/2 deprecations/)
75
- end
75
+ context "with a File deprecation_stream" do
76
+ let(:deprecation_stream) { File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w") }
77
+
78
+ it "prints a count of the deprecations" do
79
+ formatter.deprecation(:deprecated => 'i_am_deprecated')
80
+ formatter.deprecation_summary
81
+ expect(summary_stream.string).to match(/1 deprecation logged to .*deprecation_summary_example_output/)
82
+ end
83
+
84
+ it "pluralizes the reported deprecation count for more than one deprecation" do
85
+ formatter.deprecation(:deprecated => 'i_am_deprecated')
86
+ formatter.deprecation(:deprecated => 'i_am_deprecated_also')
87
+ formatter.deprecation_summary
88
+ expect(summary_stream.string).to match(/2 deprecations/)
89
+ end
90
+
91
+ it "is not printed when there are no deprecations" do
92
+ formatter.deprecation_summary
93
+ expect(summary_stream.string).to eq ""
94
+ end
76
95
 
77
- it "is not printed when there are no deprecations" do
78
- file = File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w")
79
- summary_stream = StringIO.new
80
- formatter = DeprecationFormatter.new file, summary_stream
81
- formatter.deprecation_summary
82
- summary_stream.rewind
83
- expect(summary_stream.read).to eq ""
96
+ it 'uses synchronized/non-buffered output to work around odd duplicate output behavior we have observed' do
97
+ expect {
98
+ formatter.deprecation(:deprecated => 'foo')
99
+ }.to change { deprecation_stream.sync }.from(false).to(true)
100
+ end
101
+
102
+ it 'does not print duplicate messages' do
103
+ 3.times { formatter.deprecation(:deprecated => 'foo') }
104
+ formatter.deprecation_summary
105
+
106
+ expect(summary_stream.string).to match(/1 deprecation/)
107
+ expect(File.read(deprecation_stream.path)).to eq("foo is deprecated.\n#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}")
108
+ end
84
109
  end
85
110
 
86
- it "is not printed when deprecations go to an IO instance" do
87
- summary_stream = StringIO.new
88
- formatter = DeprecationFormatter.new StringIO.new, summary_stream
89
- formatter.deprecation(:deprecated => 'i_am_deprecated')
90
- formatter.deprecation_summary
91
- summary_stream.rewind
92
- expect(summary_stream.read).to eq ""
111
+ context "with an IO deprecation_stream" do
112
+ let(:deprecation_stream) { StringIO.new }
113
+
114
+ it "groups similar deprecations together" do
115
+ formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:1")
116
+ formatter.deprecation(:deprecated => 'i_am_a_different_deprecation')
117
+ formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:2")
118
+ formatter.deprecation_summary
119
+
120
+ expected = <<-EOS.gsub(/^\s+\|/, '')
121
+ |
122
+ |Deprecation Warnings:
123
+ |
124
+ |i_am_a_different_deprecation is deprecated.
125
+ |
126
+ |i_am_deprecated is deprecated. Called from foo.rb:1.
127
+ |i_am_deprecated is deprecated. Called from foo.rb:2.
128
+ |
129
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
130
+ EOS
131
+ expect(deprecation_stream.string).to eq expected.chomp
132
+ end
133
+
134
+ it "limits the deprecation warnings after 3 calls" do
135
+ 5.times { |i| formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:#{i + 1}") }
136
+ formatter.deprecation_summary
137
+ expected = <<-EOS.gsub(/^\s+\|/, '')
138
+ |
139
+ |Deprecation Warnings:
140
+ |
141
+ |i_am_deprecated is deprecated. Called from foo.rb:1.
142
+ |i_am_deprecated is deprecated. Called from foo.rb:2.
143
+ |i_am_deprecated is deprecated. Called from foo.rb:3.
144
+ |Too many uses of deprecated 'i_am_deprecated'. Set config.deprecation_stream to a File for full output.
145
+ |
146
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
147
+ EOS
148
+ expect(deprecation_stream.string).to eq expected.chomp
149
+ end
150
+
151
+ it "limits :message deprecation warnings with different callsites after 3 calls" do
152
+ 5.times do |n|
153
+ message = "This is a long string with some callsite info: /path/#{n}/to/some/file.rb:2#{n}3. And some more stuff can come after."
154
+ formatter.deprecation(:message => message)
155
+ end
156
+ formatter.deprecation_summary
157
+ expected = <<-EOS.gsub(/^\s+\|/, '')
158
+ |
159
+ |Deprecation Warnings:
160
+ |
161
+ |This is a long string with some callsite info: /path/0/to/some/file.rb:203. And some more stuff can come after.
162
+ |This is a long string with some callsite info: /path/1/to/some/file.rb:213. And some more stuff can come after.
163
+ |This is a long string with some callsite info: /path/2/to/some/file.rb:223. And some more stuff can come after.
164
+ |Too many similar deprecation messages reported, disregarding further reports. Set config.deprecation_stream to a File for full output.
165
+ |
166
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
167
+ EOS
168
+ expect(deprecation_stream.string).to eq expected.chomp
169
+ end
170
+
171
+ it "prints the true deprecation count to the summary_stream" do
172
+ 5.times { |i| formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:#{i + 1}") }
173
+ 5.times do |n|
174
+ formatter.deprecation(:message => "callsite info: /path/#{n}/to/some/file.rb:2#{n}3. And some more stuff")
175
+ end
176
+ formatter.deprecation_summary
177
+ expect(summary_stream.string).to match(/10 deprecation warnings total/)
178
+ end
179
+
180
+ it 'does not print duplicate messages' do
181
+ 3.times { formatter.deprecation(:deprecated => 'foo') }
182
+ formatter.deprecation_summary
183
+
184
+ expect(summary_stream.string).to match(/1 deprecation/)
185
+
186
+ expected = <<-EOS.gsub(/^\s+\|/, '')
187
+ |
188
+ |Deprecation Warnings:
189
+ |
190
+ |foo is deprecated.
191
+ |
192
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
193
+ EOS
194
+
195
+ expect(deprecation_stream.string).to eq expected.chomp
196
+ end
93
197
  end
94
198
  end
95
199
  end
@@ -24,7 +24,7 @@ module RSpec
24
24
 
25
25
  let(:generated_html) do
26
26
  options = RSpec::Core::ConfigurationOptions.new(
27
- %w[spec/rspec/core/resources/formatter_specs.rb --format html --order default]
27
+ %w[spec/rspec/core/resources/formatter_specs.rb --format html --order defined]
28
28
  )
29
29
  options.parse_options
30
30
 
@@ -24,7 +24,7 @@ module RSpec
24
24
 
25
25
  let(:generated_html) do
26
26
  options = RSpec::Core::ConfigurationOptions.new(
27
- %w[spec/rspec/core/resources/formatter_specs.rb --format textmate --order default]
27
+ %w[spec/rspec/core/resources/formatter_specs.rb --format textmate --order defined]
28
28
  )
29
29
  options.parse_options
30
30
 
@@ -72,7 +72,6 @@ module RSpec
72
72
 
73
73
  expect(actual_doc.inner_html).to eq(expected_doc.inner_html)
74
74
 
75
- expect(backtrace_lines).to_not be_empty
76
75
  backtrace_lines.each do |backtrace_line|
77
76
  expect(backtrace_line['href']).to include("txmt://open?url=")
78
77
  end
@@ -26,6 +26,7 @@ module RSpec::Core
26
26
  context "when RSpec.configuration.treat_symbols_as_metadata_keys_with_true_values is set to #{config_value}" do
27
27
  before(:each) do
28
28
  Kernel.stub(:warn)
29
+ allow_deprecation unless config_value
29
30
  RSpec.configure { |c| c.treat_symbols_as_metadata_keys_with_true_values = config_value }
30
31
  end
31
32
 
@@ -57,6 +58,7 @@ module RSpec::Core
57
58
  [true, false].each do |config_value|
58
59
  context "when RSpec.configuration.treat_symbols_as_metadata_keys_with_true_values is set to #{config_value}" do
59
60
  before(:each) do
61
+ allow_deprecation unless config_value
60
62
  RSpec.configure { |c| c.treat_symbols_as_metadata_keys_with_true_values = config_value }
61
63
  end
62
64
 
@@ -56,6 +56,18 @@ module RSpec::Core
56
56
  end
57
57
 
58
58
  describe "explicit subject" do
59
+ it "yields the example in which it is eval'd" do
60
+ example_yielded_to_subject = nil
61
+ example_yielded_to_example = nil
62
+
63
+ group = ExampleGroup.describe
64
+ group.subject { |e| example_yielded_to_subject = e }
65
+ group.example { |e| subject; example_yielded_to_example = e }
66
+ group.run
67
+
68
+ expect(example_yielded_to_subject).to eq example_yielded_to_example
69
+ end
70
+
59
71
  [false, nil].each do |falsy_value|
60
72
  context "with a value of #{falsy_value.inspect}" do
61
73
  it "is evaluated once per example" do
@@ -70,7 +82,7 @@ module RSpec::Core
70
82
  subject
71
83
  subject
72
84
  end
73
- expect(group.run).to be_true, "expected subject block to be evaluated only once"
85
+ expect(group.run).to be_truthy, "expected subject block to be evaluated only once"
74
86
  end
75
87
  end
76
88
  end
@@ -184,6 +196,18 @@ module RSpec::Core
184
196
  end
185
197
 
186
198
  describe "with a name" do
199
+ it "yields the example in which it is eval'd" do
200
+ example_yielded_to_subject = nil
201
+ example_yielded_to_example = nil
202
+
203
+ group = ExampleGroup.describe
204
+ group.subject(:foo) { |e| example_yielded_to_subject = e }
205
+ group.example { |e| foo; example_yielded_to_example = e }
206
+ group.run
207
+
208
+ expect(example_yielded_to_subject).to eq example_yielded_to_example
209
+ end
210
+
187
211
  it "defines a method that returns the memoized subject" do
188
212
  list_value_1 = list_value_2 = subject_value_1 = subject_value_2 = nil
189
213
 
@@ -319,152 +343,160 @@ module RSpec::Core
319
343
  it { should_not be_not_ok }
320
344
  end
321
345
 
322
- expect(group.run).to be_true
346
+ expect(group.run).to be_truthy
323
347
  end
324
348
  end
325
349
 
326
350
  describe "#its" do
327
- subject do
328
- Class.new do
329
- def initialize
330
- @call_count = 0
331
- end
332
-
333
- def call_count
334
- @call_count += 1
335
- end
336
- end.new
337
- end
338
-
339
- context "with a call counter" do
340
- its(:call_count) { should eq(1) }
341
- end
351
+ extend SilenceDSLDeprecations
352
+ silence_dsl_deprecations do
353
+ it "should issue deprecation warning" do
354
+ expect_deprecation_with_call_site(__FILE__, __LINE__+1, '`its` method')
355
+ RSpec::Core::ExampleGroup.its(nil) {}
356
+ end
342
357
 
343
- context "with nil value" do
344
358
  subject do
345
359
  Class.new do
346
- def nil_value
347
- nil
360
+ def initialize
361
+ @call_count = 0
348
362
  end
349
- end.new
350
- end
351
- its(:nil_value) { should be_nil }
352
- end
353
363
 
354
- context "with nested attributes" do
355
- subject do
356
- Class.new do
357
- def name
358
- "John"
364
+ def call_count
365
+ @call_count += 1
359
366
  end
360
367
  end.new
361
368
  end
362
- its("name") { should eq("John") }
363
- its("name.size") { should eq(4) }
364
- its("name.size.class") { should eq(Fixnum) }
365
- end
366
369
 
367
- context "when it responds to #[]" do
368
- subject do
369
- Class.new do
370
- def [](*objects)
371
- objects.map do |object|
372
- "#{object.class}: #{object.to_s}"
373
- end.join("; ")
374
- end
370
+ context "with a call counter" do
371
+ its(:call_count) { should eq(1) }
372
+ end
375
373
 
376
- def name
377
- "George"
378
- end
379
- end.new
374
+ context "with nil value" do
375
+ subject do
376
+ Class.new do
377
+ def nil_value
378
+ nil
379
+ end
380
+ end.new
381
+ end
382
+ its(:nil_value) { should be_nil }
380
383
  end
381
- its([:a]) { should eq("Symbol: a") }
382
- its(['a']) { should eq("String: a") }
383
- its([:b, 'c', 4]) { should eq("Symbol: b; String: c; Fixnum: 4") }
384
- its(:name) { should eq("George") }
385
- context "when referring to an attribute without the proper array syntax" do
386
- context "it raises an error" do
387
- its(:age) do
388
- expect do
389
- should eq(64)
390
- end.to raise_error(NoMethodError)
384
+
385
+ context "with nested attributes" do
386
+ subject do
387
+ Class.new do
388
+ def name
389
+ "John"
390
+ end
391
+ end.new
392
+ end
393
+ its("name") { should eq("John") }
394
+ its("name.size") { should eq(4) }
395
+ its("name.size.class") { should eq(Fixnum) }
396
+ end
397
+
398
+ context "when it responds to #[]" do
399
+ subject do
400
+ Class.new do
401
+ def [](*objects)
402
+ objects.map do |object|
403
+ "#{object.class}: #{object.to_s}"
404
+ end.join("; ")
405
+ end
406
+
407
+ def name
408
+ "George"
409
+ end
410
+ end.new
411
+ end
412
+ its([:a]) { should eq("Symbol: a") }
413
+ its(['a']) { should eq("String: a") }
414
+ its([:b, 'c', 4]) { should eq("Symbol: b; String: c; Fixnum: 4") }
415
+ its(:name) { should eq("George") }
416
+ context "when referring to an attribute without the proper array syntax" do
417
+ context "it raises an error" do
418
+ its(:age) do
419
+ expect do
420
+ should eq(64)
421
+ end.to raise_error(NoMethodError)
422
+ end
391
423
  end
392
424
  end
393
425
  end
394
- end
395
426
 
396
- context "when it does not respond to #[]" do
397
- subject { Object.new }
427
+ context "when it does not respond to #[]" do
428
+ subject { Object.new }
398
429
 
399
- context "it raises an error" do
400
- its([:a]) do
401
- expect do
402
- should eq("Symbol: a")
403
- end.to raise_error(NoMethodError)
430
+ context "it raises an error" do
431
+ its([:a]) do
432
+ expect do
433
+ should eq("Symbol: a")
434
+ end.to raise_error(NoMethodError)
435
+ end
404
436
  end
405
437
  end
406
- end
407
438
 
408
- context "calling and overriding super" do
409
- it "calls to the subject defined in the parent group" do
410
- group = ExampleGroup.describe(Array) do
411
- subject { [1, 'a'] }
439
+ context "calling and overriding super" do
440
+ it "calls to the subject defined in the parent group" do
441
+ group = ExampleGroup.describe(Array) do
442
+ subject { [1, 'a'] }
412
443
 
413
- its(:last) { should eq("a") }
444
+ its(:last) { should eq("a") }
414
445
 
415
- describe '.first' do
416
- def subject; super().first; end
446
+ describe '.first' do
447
+ def subject; super().first; end
417
448
 
418
- its(:next) { should eq(2) }
449
+ its(:next) { should eq(2) }
450
+ end
419
451
  end
420
- end
421
452
 
422
- expect(group.run).to be_true
453
+ expect(group.run).to be_truthy
454
+ end
423
455
  end
424
- end
425
456
 
426
- context "with nil subject" do
427
- subject do
428
- Class.new do
429
- def initialize
430
- @counter = -1
431
- end
432
- def nil_if_first_time
433
- @counter += 1
434
- @counter == 0 ? nil : true
435
- end
436
- end.new
457
+ context "with nil subject" do
458
+ subject do
459
+ Class.new do
460
+ def initialize
461
+ @counter = -1
462
+ end
463
+ def nil_if_first_time
464
+ @counter += 1
465
+ @counter == 0 ? nil : true
466
+ end
467
+ end.new
468
+ end
469
+ its(:nil_if_first_time) { should be(nil) }
437
470
  end
438
- its(:nil_if_first_time) { should be(nil) }
439
- end
440
471
 
441
- context "with false subject" do
442
- subject do
443
- Class.new do
444
- def initialize
445
- @counter = -1
446
- end
447
- def false_if_first_time
448
- @counter += 1
449
- @counter > 0
450
- end
451
- end.new
472
+ context "with false subject" do
473
+ subject do
474
+ Class.new do
475
+ def initialize
476
+ @counter = -1
477
+ end
478
+ def false_if_first_time
479
+ @counter += 1
480
+ @counter > 0
481
+ end
482
+ end.new
483
+ end
484
+ its(:false_if_first_time) { should be(false) }
452
485
  end
453
- its(:false_if_first_time) { should be(false) }
454
- end
455
486
 
456
- describe 'accessing `subject` in `before` and `let`' do
457
- subject { 'my subject' }
458
- before { @subject_in_before = subject }
459
- let(:subject_in_let) { subject }
460
- let!(:eager_loaded_subject_in_let) { subject }
461
-
462
- # These examples read weird, because we're actually
463
- # specifying the behaviour of `its` itself
464
- its(nil) { expect(subject).to eq('my subject') }
465
- its(nil) { expect(@subject_in_before).to eq('my subject') }
466
- its(nil) { expect(subject_in_let).to eq('my subject') }
467
- its(nil) { expect(eager_loaded_subject_in_let).to eq('my subject') }
487
+ describe 'accessing `subject` in `before` and `let`' do
488
+ subject { 'my subject' }
489
+ before { @subject_in_before = subject }
490
+ let(:subject_in_let) { subject }
491
+ let!(:eager_loaded_subject_in_let) { subject }
492
+
493
+ # These examples read weird, because we're actually
494
+ # specifying the behaviour of `its` itself
495
+ its(nil) { expect(subject).to eq('my subject') }
496
+ its(nil) { expect(@subject_in_before).to eq('my subject') }
497
+ its(nil) { expect(subject_in_let).to eq('my subject') }
498
+ its(nil) { expect(eager_loaded_subject_in_let).to eq('my subject') }
499
+ end
468
500
  end
469
501
  end
470
502
 
@@ -516,6 +548,15 @@ module RSpec::Core
516
548
  expect(@nil_value_count).to eq(1)
517
549
  end
518
550
 
551
+ let(:yield_the_example) do |example_yielded_to_let|
552
+ @example_yielded_to_let = example_yielded_to_let
553
+ end
554
+
555
+ it "yields the example" do |example_yielded_to_example|
556
+ yield_the_example
557
+ expect(@example_yielded_to_let).to equal example_yielded_to_example
558
+ end
559
+
519
560
  let(:regex_with_capture) { %r[RegexWithCapture(\d)] }
520
561
 
521
562
  it 'does not pass the block up the ancestor chain' do