rspec-core 2.13.0 → 2.13.1

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.
@@ -1,3 +1,33 @@
1
+ ### 2.13.1 / 2013-03-12
2
+ [full changelog](http://github.com/rspec/rspec-core/compare/v2.13.0...v2.13.1)
3
+
4
+ Bug fixes
5
+
6
+ * Use hook classes as proxies rather than extending hook blocks to support
7
+ lambdas for before/after/around hooks. (David Chelimsky)
8
+ * Fix regression in 2.13.0 that caused confusing behavior when overriding
9
+ a named subject with an unnamed subject in an inner group and then
10
+ referencing the outer group subject's name. The fix for this required
11
+ us to disallow using `super` in a named subject (which is confusing,
12
+ anyway -- named subjects create 2 methods, so which method on the
13
+ parent example group are you `super`ing to?) but `super` in an unnamed
14
+ subject continues to work (Myron Marston).
15
+ * Do not allow a referenced `let` or `subject` in `before(:all)` to cause
16
+ other `let` declarations to leak across examples (Myron Marston).
17
+ * Work around odd ruby 1.9 bug with `String#match` that was triggered
18
+ by passing it a regex from a `let` declaration. For more info, see
19
+ http://bugs.ruby-lang.org/issues/8059 (Aaron Kromer).
20
+ * Add missing `require 'set'` to `base_text_formatter.rb` (Tom
21
+ Anderson).
22
+
23
+ Deprecations
24
+
25
+ * Deprecate accessing `let` or `subject` declarations in `before(:all)`.
26
+ These were not intended to be called in a `before(:all)` hook, as
27
+ they exist to define state that is reset between each example, while
28
+ `before(:all)` exists to define state that is shared across examples
29
+ in an example group (Myron Marston).
30
+
1
31
  ### 2.13.0 / 2013-02-23
2
32
  [full changelog](http://github.com/rspec/rspec-core/compare/v2.12.2...v2.13.0)
3
33
 
@@ -14,6 +44,8 @@ Enhancements
14
44
  method. (Myron Marston)
15
45
  * Allow output colors to be configured individually.
16
46
  (Charlie Maffitt)
47
+ * Always dump slow examples when `--profile` option is given,
48
+ even when an example failed (Myron Marston).
17
49
 
18
50
  Bug fixes
19
51
 
data/README.md CHANGED
@@ -198,8 +198,10 @@ this before you write any implementation code:
198
198
  ```ruby
199
199
  # in spec/calculator_spec.rb
200
200
  describe Calculator do
201
- it "add(x,y) returns the sum of its arguments" do
202
- expect(Calculator.new.add(1, 2)).to eq(3)
201
+ describe '#add' do
202
+ it 'returns the sum of its arguments' do
203
+ expect(Calculator.new.add(1, 2)).to eq(3)
204
+ end
203
205
  end
204
206
  end
205
207
  ```
@@ -244,8 +246,9 @@ Use the `documentation` formatter to see the resulting spec:
244
246
 
245
247
  ```
246
248
  $ rspec spec/calculator_spec.rb --format doc
247
- Calculator add
248
- returns the sum of its arguments
249
+ Calculator
250
+ #add
251
+ returns the sum of its arguments
249
252
 
250
253
  Finished in 0.000379 seconds
251
254
  1 example, 0 failures
@@ -31,10 +31,6 @@ Then /^the process should succeed even though no examples were run$/ do
31
31
  step %q{the exit status should be 0}
32
32
  end
33
33
 
34
- Then /^the file "([^"]*)" should contain:$/ do |file, partial_content|
35
- check_file_content(file, partial_content, true)
36
- end
37
-
38
34
  Then /^the backtrace\-normalized output should contain:$/ do |partial_output|
39
35
  # ruby 1.9 includes additional stuff in the backtrace,
40
36
  # so we need to normalize it to compare it with our expected output.
@@ -1,12 +1,14 @@
1
1
  require 'aruba/cucumber'
2
2
 
3
+ timeouts = { 'java' => 60 }
4
+
3
5
  Before do
4
- if RUBY_PLATFORM =~ /java/
5
- # ideas taken from: http://blog.headius.com/2010/03/jruby-startup-time-tips.html
6
- set_env('JRUBY_OPTS', '-X-C') # disable JIT since these processes are so short lived
7
- set_env('JAVA_OPTS', '-d32') # force jRuby to use client JVM for faster startup times
8
- @aruba_timeout_seconds = 60
9
- else
10
- @aruba_timeout_seconds = 10
11
- end
6
+ @aruba_timeout_seconds = timeouts.fetch(RUBY_PLATFORM) { 10 }
12
7
  end
8
+
9
+ Aruba.configure do |config|
10
+ config.before_cmd do |cmd|
11
+ set_env('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") # disable JIT since these processes are so short lived
12
+ end
13
+ end if RUBY_PLATFORM == 'java'
14
+
@@ -299,6 +299,7 @@ module RSpec
299
299
  # @private
300
300
  def self.store_before_all_ivars(example_group_instance)
301
301
  return if example_group_instance.instance_variables.empty?
302
+
302
303
  example_group_instance.instance_variables.each { |ivar|
303
304
  before_all_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
304
305
  }
@@ -314,7 +315,10 @@ module RSpec
314
315
  return if descendant_filtered_examples.empty?
315
316
  begin
316
317
  assign_before_all_ivars(superclass.before_all_ivars, example_group_instance)
317
- run_hook(:before, :all, example_group_instance)
318
+
319
+ BeforeAllMemoizedHash.isolate_for_before_all(example_group_instance) do
320
+ run_hook(:before, :all, example_group_instance)
321
+ end
318
322
  ensure
319
323
  store_before_all_ivars(example_group_instance)
320
324
  end
@@ -1,4 +1,5 @@
1
1
  require 'rspec/core/formatters/base_formatter'
2
+ require 'set'
2
3
 
3
4
  module RSpec
4
5
  module Core
@@ -3,12 +3,12 @@ module RSpec
3
3
  module Hooks
4
4
  include MetadataHashBuilder::WithConfigWarning
5
5
 
6
- module HookExtension
7
- attr_reader :options
6
+ class Hook
7
+ attr_reader :block, :options
8
8
 
9
- def with(options)
9
+ def initialize(block, options)
10
+ @block = block
10
11
  @options = options
11
- self
12
12
  end
13
13
 
14
14
  def options_apply?(example_or_group)
@@ -16,11 +16,9 @@ module RSpec
16
16
  end
17
17
  end
18
18
 
19
- module BeforeHookExtension
20
- include HookExtension
21
-
19
+ class BeforeHook < Hook
22
20
  def run(example)
23
- example.instance_eval(&self)
21
+ example.instance_eval(&block)
24
22
  end
25
23
 
26
24
  def display_name
@@ -28,11 +26,9 @@ module RSpec
28
26
  end
29
27
  end
30
28
 
31
- module AfterHookExtension
32
- include HookExtension
33
-
29
+ class AfterHook < Hook
34
30
  def run(example)
35
- example.instance_eval_with_rescue("in an after hook", &self)
31
+ example.instance_eval_with_rescue("in an after hook", &block)
36
32
  end
37
33
 
38
34
  def display_name
@@ -40,9 +36,7 @@ module RSpec
40
36
  end
41
37
  end
42
38
 
43
- module AroundHookExtension
44
- include HookExtension
45
-
39
+ class AroundHook < Hook
46
40
  def display_name
47
41
  "around hook"
48
42
  end
@@ -90,7 +84,7 @@ module RSpec
90
84
  def run
91
85
  inject(@initial_procsy) do |procsy, around_hook|
92
86
  Example.procsy(procsy.metadata) do
93
- @example.instance_eval_with_args(procsy, &around_hook)
87
+ @example.instance_eval_with_args(procsy, &around_hook.block)
94
88
  end
95
89
  end.call
96
90
  end
@@ -433,10 +427,10 @@ module RSpec
433
427
 
434
428
  SCOPES = [:each, :all, :suite]
435
429
 
436
- EXTENSIONS = {
437
- :before => BeforeHookExtension,
438
- :after => AfterHookExtension,
439
- :around => AroundHookExtension
430
+ HOOK_TYPES = {
431
+ :before => BeforeHook,
432
+ :after => AfterHook,
433
+ :around => AroundHook
440
434
  }
441
435
 
442
436
  def before_all_hooks_for(group)
@@ -457,7 +451,7 @@ module RSpec
457
451
 
458
452
  def register_hook prepend_or_append, hook, *args, &block
459
453
  scope, options = scope_and_options_from(*args)
460
- hooks[hook][scope].send(prepend_or_append, block.extend(EXTENSIONS[hook]).with(options))
454
+ hooks[hook][scope].send(prepend_or_append, HOOK_TYPES[hook].new(block, options))
461
455
  end
462
456
 
463
457
  def find_hook(hook, scope, example_or_group, initial_procsy)
@@ -78,6 +78,66 @@ module RSpec
78
78
  @__memoized ||= {}
79
79
  end
80
80
 
81
+ # Used internally to customize the behavior of the
82
+ # memoized hash when used in a `before(:all)` hook.
83
+ #
84
+ # @private
85
+ class BeforeAllMemoizedHash
86
+ def initialize(example_group_instance)
87
+ @example_group_instance = example_group_instance
88
+ @hash = {}
89
+ end
90
+
91
+ def self.isolate_for_before_all(example_group_instance)
92
+ example_group_instance.instance_eval do
93
+ @__memoized = BeforeAllMemoizedHash.new(self)
94
+
95
+ begin
96
+ yield
97
+ ensure
98
+ @__memoized.preserve_accessed_lets
99
+ @__memoized = nil
100
+ end
101
+ end
102
+ end
103
+
104
+ def fetch(key, &block)
105
+ description = if key == :subject
106
+ "subject"
107
+ else
108
+ "let declaration `#{key}`"
109
+ end
110
+
111
+ ::RSpec.warn_deprecation <<-EOS
112
+ WARNING: #{description} accessed in a `before(:all)` hook at:
113
+ #{caller[1]}
114
+
115
+ This is deprecated behavior that will not be supported in RSpec 3.
116
+
117
+ `let` and `subject` declarations are not intended to be called
118
+ in a `before(:all)` hook, as they exist to define state that
119
+ is reset between each example, while `before(:all)` exists to
120
+ define state that is shared across examples in an example group.
121
+ EOS
122
+
123
+ @hash.fetch(key, &block)
124
+ end
125
+
126
+ def []=(key, value)
127
+ @hash[key] = value
128
+ end
129
+
130
+ def preserve_accessed_lets
131
+ hash = @hash
132
+
133
+ @example_group_instance.class.class_eval do
134
+ hash.each do |key, value|
135
+ define_method(key) { value }
136
+ end
137
+ end
138
+ end
139
+ end
140
+
81
141
  def self.included(mod)
82
142
  mod.extend(ClassMethods)
83
143
 
@@ -117,12 +177,12 @@ module RSpec
117
177
  def let(name, &block)
118
178
  # We have to pass the block directly to `define_method` to
119
179
  # allow it to use method constructs like `super` and `return`.
120
- ::RSpec::Core::MemoizedHelpers.module_for(self).define_method(name, &block)
180
+ MemoizedHelpers.module_for(self).define_method(name, &block)
121
181
 
122
182
  # Apply the memoization. The method has been defined in an ancestor
123
183
  # module so we can use `super` here to get the value.
124
184
  define_method(name) do
125
- __memoized.fetch(name) { |k| __memoized[k] = super() }
185
+ __memoized.fetch(name) { |k| __memoized[k] = super(&nil) }
126
186
  end
127
187
  end
128
188
 
@@ -214,8 +274,16 @@ module RSpec
214
274
  #
215
275
  # @see MemoizedHelpers#should
216
276
  def subject(name=nil, &block)
217
- let(:subject, &block)
218
- alias_method name, :subject if name
277
+ if name
278
+ let(name, &block)
279
+ subject { __send__ name }
280
+
281
+ self::NamedSubjectPreventSuper.define_method(name) do
282
+ raise NotImplementedError, "`super` in named subjects is not supported"
283
+ end
284
+ else
285
+ let(:subject, &block)
286
+ end
219
287
  end
220
288
 
221
289
  # Just like `subject`, except the block is invoked by an implicit `before`
@@ -381,9 +449,17 @@ module RSpec
381
449
  # in order to get the value to memoize.
382
450
  def self.module_for(example_group)
383
451
  get_constant_or_yield(example_group, :LetDefinitions) do
384
- # Expose `define_method` as a public method, so we can
385
- # easily use it below.
386
- mod = Module.new { public_class_method :define_method }
452
+ mod = Module.new do
453
+ include Module.new {
454
+ public_class_method :define_method
455
+ example_group.const_set(:NamedSubjectPreventSuper, self)
456
+ }
457
+
458
+ # Expose `define_method` as a public method, so we can
459
+ # easily use it below.
460
+ public_class_method :define_method
461
+ end
462
+
387
463
  example_group.__send__(:include, mod)
388
464
  example_group.const_set(:LetDefinitions, mod)
389
465
  mod
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Core
3
3
  module Version
4
- STRING = '2.13.0'
4
+ STRING = '2.13.1'
5
5
  end
6
6
  end
7
7
  end
@@ -992,7 +992,7 @@ module RSpec::Core
992
992
 
993
993
  describe "#output=" do
994
994
  it "sets the output" do
995
- output = mock("output")
995
+ output = double("output")
996
996
  config.output = output
997
997
  expect(config.output).to equal(output)
998
998
  end
@@ -330,7 +330,7 @@ describe RSpec::Core::Example, :parent_metadata => 'sample' do
330
330
  it 'does not print mock expectation errors' do
331
331
  group = RSpec::Core::ExampleGroup.describe do
332
332
  example do
333
- foo = mock
333
+ foo = double
334
334
  foo.should_receive(:bar)
335
335
  raise "boom"
336
336
  end
@@ -28,21 +28,21 @@ describe RSpec::Core::Formatters::BaseFormatter do
28
28
 
29
29
  describe "read_failed_line" do
30
30
  it "deals gracefully with a heterogeneous language stack trace" do
31
- exception = mock(:Exception, :backtrace => [
31
+ exception = double(:Exception, :backtrace => [
32
32
  "at Object.prototypeMethod (foo:331:18)",
33
33
  "at Array.forEach (native)",
34
34
  "at a_named_javascript_function (/some/javascript/file.js:39:5)",
35
35
  "/some/line/of/ruby.rb:14"
36
36
  ])
37
- example = mock(:Example, :file_path => __FILE__)
37
+ example = double(:Example, :file_path => __FILE__)
38
38
  expect {
39
39
  formatter.send(:read_failed_line, exception, example)
40
40
  }.not_to raise_error
41
41
  end
42
42
 
43
43
  it "deals gracefully with a security error" do
44
- exception = mock(:Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"])
45
- example = mock(:Example, :file_path => __FILE__)
44
+ exception = double(:Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"])
45
+ example = double(:Example, :file_path => __FILE__)
46
46
  safely do
47
47
  expect {
48
48
  formatter.send(:read_failed_line, exception, example)
@@ -52,8 +52,8 @@ describe RSpec::Core::Formatters::BaseFormatter do
52
52
 
53
53
  context "when ruby reports a bogus line number in the stack trace" do
54
54
  it "reports the filename and that it was unable to find the matching line" do
55
- exception = mock(:Exception, :backtrace => [ "#{__FILE__}:10000000" ])
56
- example = mock(:Example, :file_path => __FILE__)
55
+ exception = double(:Exception, :backtrace => [ "#{__FILE__}:10000000" ])
56
+ example = double(:Example, :file_path => __FILE__)
57
57
 
58
58
  msg = formatter.send(:read_failed_line, exception, example)
59
59
  expect(msg).to include("Unable to find matching line")
@@ -75,11 +75,11 @@ describe RSpec::Core::Formatters::BaseFormatter do
75
75
 
76
76
  it "doesn't hang when file exists" do
77
77
  pending("This issue still exists on JRuby, but should be resolved shortly: https://github.com/rspec/rspec-core/issues/295", :if => RUBY_PLATFORM == 'java')
78
- exception = mock(:Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"])
78
+ exception = double(:Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"])
79
79
 
80
- example = mock(:Example, :file_path => __FILE__)
80
+ example = double(:Example, :file_path => __FILE__)
81
81
  expect(formatter.send(:read_failed_line, exception, example)).to eql(
82
- %Q{ exception = mock(:Exception, :backtrace => [ "\#{__FILE__}:\#{__LINE__}"])\n})
82
+ %Q{ exception = double(:Exception, :backtrace => [ "\#{__FILE__}:\#{__LINE__}"])\n})
83
83
  end
84
84
 
85
85
  end
@@ -101,7 +101,7 @@ describe RSpec::Core::Formatters::BaseFormatter do
101
101
  end
102
102
 
103
103
  it "removes lines from rspec and lines that come before the invocation of the at_exit autorun hook" do
104
- expect(formatter.format_backtrace(backtrace, stub.as_null_object)).to eq(["./my_spec.rb:5"])
104
+ expect(formatter.format_backtrace(backtrace, double.as_null_object)).to eq(["./my_spec.rb:5"])
105
105
  end
106
106
  end
107
107
 
@@ -246,5 +246,22 @@ module RSpec::Core
246
246
  end
247
247
  end
248
248
  end
249
+
250
+ describe "lambda" do
251
+ it "can be used as a hook" do
252
+ messages = []
253
+ count = 0
254
+ hook = lambda {|e| messages << "hook #{count = count + 1}"; e.run }
255
+
256
+ RSpec.configure do |c|
257
+ c.around(:each, &hook)
258
+ c.around(:each, &hook)
259
+ end
260
+
261
+ group = ExampleGroup.describe { example { messages << "example" } }
262
+ group.run
263
+ expect(messages).to eq ["hook 1", "hook 2", "example"]
264
+ end
265
+ end
249
266
  end
250
267
  end
@@ -120,6 +120,67 @@ module RSpec::Core
120
120
 
121
121
  expect(subject_value).to eq([4, 5, 6, :override])
122
122
  end
123
+
124
+ context 'when referenced in a `before(:all)` hook' do
125
+ before do
126
+ expect(::RSpec).to respond_to(:warn_deprecation)
127
+ ::RSpec.stub(:warn_deprecation)
128
+ end
129
+
130
+ def define_and_run_group
131
+ values = { :reference_lines => [] }
132
+
133
+ ExampleGroup.describe do
134
+ subject { [1, 2] }
135
+ let(:list) { %w[ a b ] }
136
+
137
+ before(:all) do
138
+ subject << 3; values[:reference_lines] << __LINE__
139
+ values[:final_subject_value_in_before_all] = subject; values[:reference_lines] << __LINE__
140
+ end
141
+
142
+ example do
143
+ list << '1'
144
+ values[:list_in_ex_1] = list
145
+ values[:subject_value_in_example] = subject
146
+ end
147
+
148
+ example do
149
+ list << '2'
150
+ values[:list_in_ex_2] = list
151
+ end
152
+ end.run
153
+
154
+ values
155
+ end
156
+
157
+ it 'memoizes the value within the before(:all) hook' do
158
+ values = define_and_run_group
159
+ expect(values.fetch(:final_subject_value_in_before_all)).to eq([1, 2, 3])
160
+ end
161
+
162
+ it 'preserves the memoization into the individual examples' do
163
+ values = define_and_run_group
164
+ expect(values.fetch(:subject_value_in_example)).to eq([1, 2, 3])
165
+ end
166
+
167
+ it 'does not cause other lets to be shared across examples' do
168
+ values = define_and_run_group
169
+ expect(values.fetch(:list_in_ex_1)).to eq(%w[ a b 1 ])
170
+ expect(values.fetch(:list_in_ex_2)).to eq(%w[ a b 2 ])
171
+ end
172
+
173
+ it 'prints a warning since `subject` declarations are not intended to be used in :all hooks' do
174
+ msgs = []
175
+ ::RSpec.stub(:warn_deprecation) { |msg| msgs << msg }
176
+
177
+ values = define_and_run_group
178
+
179
+ expect(msgs).to include(*values[:reference_lines].map { |line|
180
+ match(/subject accessed.*#{__FILE__}:#{line}/m)
181
+ })
182
+ end
183
+ end
123
184
  end
124
185
 
125
186
  describe "with a name" do
@@ -157,21 +218,75 @@ module RSpec::Core
157
218
  expect(inner_subject_value).to eq(1)
158
219
  end
159
220
 
221
+ it 'can continue to be referenced by the name even when an inner group redefines the subject' do
222
+ named_value = nil
223
+
224
+ ExampleGroup.describe do
225
+ subject(:named) { :outer }
226
+
227
+ describe "inner" do
228
+ subject { :inner }
229
+ example do
230
+ subject # so the inner subject method is run and memoized
231
+ named_value = self.named
232
+ end
233
+ end
234
+ end.run
235
+
236
+ expect(named_value).to eq(:outer)
237
+ end
238
+
239
+ it 'can continue to reference an inner subject after the outer subject name is referenced' do
240
+ subject_value = nil
241
+
242
+ ExampleGroup.describe do
243
+ subject(:named) { :outer }
244
+
245
+ describe "inner" do
246
+ subject { :inner }
247
+ example do
248
+ named # so the outer subject method is run and memoized
249
+ subject_value = self.subject
250
+ end
251
+ end
252
+ end.run
253
+
254
+ expect(subject_value).to eq(:inner)
255
+ end
256
+
160
257
  context 'when `super` is used' do
161
- it "delegates to the parent context's `subject`, not the named mehtod" do
162
- inner_subject_value = nil
258
+ def should_raise_not_supported_error(&block)
259
+ ex = nil
163
260
 
164
261
  ExampleGroup.describe do
165
262
  let(:list) { ["a", "b", "c"] }
166
263
  subject { [1, 2, 3] }
167
264
 
168
265
  describe 'first' do
266
+ module_eval(&block) if block
267
+
169
268
  subject(:list) { super().first(2) }
170
- example { inner_subject_value = subject }
269
+ ex = example { subject }
171
270
  end
172
271
  end.run
173
272
 
174
- expect(inner_subject_value).to eq([1, 2])
273
+ expect(ex.execution_result[:status]).to eq("failed")
274
+ expect(ex.execution_result[:exception].message).to match(/super.*not supported/)
275
+ end
276
+
277
+ it 'raises a "not supported" error' do
278
+ should_raise_not_supported_error
279
+ end
280
+
281
+ context 'with a `let` definition before the named subject' do
282
+ it 'raises a "not supported" error' do
283
+ should_raise_not_supported_error do
284
+ # My first pass implementation worked unless there was a `let`
285
+ # declared before the named subject -- this let is in place to
286
+ # ensure that bug doesn't return.
287
+ let(:foo) { 3 }
288
+ end
289
+ end
175
290
  end
176
291
  end
177
292
  end
@@ -386,6 +501,13 @@ module RSpec::Core
386
501
  expect(@nil_value_count).to eq(1)
387
502
  end
388
503
 
504
+ let(:regex_with_capture) { %r[RegexWithCapture(\d)] }
505
+
506
+ it 'does not pass the block up the ancestor chain' do
507
+ # Test for Ruby bug http://bugs.ruby-lang.org/issues/8059
508
+ expect("RegexWithCapture1".match(regex_with_capture)[1]).to eq('1')
509
+ end
510
+
389
511
  let(:a_value) { "a string" }
390
512
 
391
513
  context 'when overriding let in a nested context' do
@@ -412,6 +534,67 @@ module RSpec::Core
412
534
  expect(value).to eq(:late_exit)
413
535
  end
414
536
  end
537
+
538
+ context 'when referenced in a `before(:all)` hook' do
539
+ before do
540
+ expect(::RSpec).to respond_to(:warn_deprecation)
541
+ ::RSpec.stub(:warn_deprecation)
542
+ end
543
+
544
+ def define_and_run_group
545
+ values = { :reference_lines => [] }
546
+
547
+ ExampleGroup.describe do
548
+ let(:list) { [1, 2] }
549
+ subject { %w[ a b ] }
550
+
551
+ before(:all) do
552
+ list << 3; values[:reference_lines] << __LINE__
553
+ values[:final_list_value_in_before_all] = list; values[:reference_lines] << __LINE__
554
+ end
555
+
556
+ example do
557
+ subject << "1"
558
+ values[:subject_in_ex_1] = subject
559
+ values[:list_value_in_example] = list
560
+ end
561
+
562
+ example do
563
+ subject << "2"
564
+ values[:subject_in_ex_2] = subject
565
+ end
566
+ end.run
567
+
568
+ values
569
+ end
570
+
571
+ it 'memoizes the value within the before(:all) hook' do
572
+ values = define_and_run_group
573
+ expect(values.fetch(:final_list_value_in_before_all)).to eq([1, 2, 3])
574
+ end
575
+
576
+ it 'preserves the memoized value into the examples' do
577
+ values = define_and_run_group
578
+ expect(values.fetch(:list_value_in_example)).to eq([1, 2, 3])
579
+ end
580
+
581
+ it 'does not cause the subject to be shared across examples' do
582
+ values = define_and_run_group
583
+ expect(values.fetch(:subject_in_ex_1)).to eq(%w[ a b 1 ])
584
+ expect(values.fetch(:subject_in_ex_2)).to eq(%w[ a b 2 ])
585
+ end
586
+
587
+ it 'prints a warning since `let` declarations are not intended to be used in :all hooks' do
588
+ msgs = []
589
+ ::RSpec.stub(:warn_deprecation) { |msg| msgs << msg }
590
+
591
+ values = define_and_run_group
592
+
593
+ expect(msgs).to include(*values[:reference_lines].map { |line|
594
+ match(/let declaration `list` accessed.*#{__FILE__}:#{line}/m)
595
+ })
596
+ end
597
+ end
415
598
  end
416
599
 
417
600
  describe "#let!" do
@@ -456,3 +639,4 @@ module RSpec::Core
456
639
  end
457
640
  end
458
641
  end
642
+
@@ -18,7 +18,7 @@ describe "an example" do
18
18
  end
19
19
  end
20
20
  example = group.examples.first
21
- example.run(group.new, stub.as_null_object)
21
+ example.run(group.new, double.as_null_object)
22
22
  expect(example).to be_pending_with('just because')
23
23
  end
24
24
 
@@ -28,7 +28,7 @@ describe "an example" do
28
28
  end
29
29
  end
30
30
  example = group.examples.first
31
- example.run(group.new, stub.as_null_object)
31
+ example.run(group.new, double.as_null_object)
32
32
  expect(example).to be_pending_with('No reason given')
33
33
  end
34
34
  end
@@ -39,7 +39,7 @@ describe "an example" do
39
39
  it "has no block"
40
40
  end
41
41
  example = group.examples.first
42
- example.run(group.new, stub.as_null_object)
42
+ example.run(group.new, double.as_null_object)
43
43
  expect(example).to be_pending_with('Not yet implemented')
44
44
  end
45
45
  end
@@ -52,7 +52,7 @@ describe "an example" do
52
52
  end
53
53
  end
54
54
  example = group.examples.first
55
- example.run(group.new, stub.as_null_object)
55
+ example.run(group.new, double.as_null_object)
56
56
  expect(example).to be_pending_with(RSpec::Core::Pending::NO_REASON_GIVEN)
57
57
  end
58
58
  end
@@ -69,7 +69,7 @@ describe "an example" do
69
69
  end
70
70
  end
71
71
  example = group.examples.last
72
- example.run(group.new, stub.as_null_object)
72
+ example.run(group.new, double.as_null_object)
73
73
  expect(example.description).to match(/example at/)
74
74
  end
75
75
  end
@@ -85,7 +85,7 @@ describe "an example" do
85
85
  end
86
86
  end
87
87
  example = group.examples.last
88
- example.run(group.new, stub.as_null_object)
88
+ example.run(group.new, double.as_null_object)
89
89
  expect(example.description).to match(/example at/)
90
90
  end
91
91
  end
@@ -99,7 +99,7 @@ describe "an example" do
99
99
  end
100
100
  end
101
101
  example = group.examples.first
102
- example.run(group.new, stub.as_null_object)
102
+ example.run(group.new, double.as_null_object)
103
103
  expect(example).to be_pending_with('just because')
104
104
  end
105
105
  end
@@ -112,7 +112,7 @@ describe "an example" do
112
112
  end
113
113
  end
114
114
  example = group.examples.first
115
- example.run(group.new, stub.as_null_object)
115
+ example.run(group.new, double.as_null_object)
116
116
  example
117
117
  end
118
118
 
@@ -30,7 +30,7 @@ module RSpec::Core
30
30
  it "passes example_group_started and example_group_finished messages to that formatter in that order" do
31
31
  order = []
32
32
 
33
- formatter = stub("formatter").as_null_object
33
+ formatter = double("formatter").as_null_object
34
34
  formatter.stub(:example_group_started) { |group| order << "Started: #{group.description}" }
35
35
  formatter.stub(:example_group_finished) { |group| order << "Finished: #{group.description}" }
36
36
 
@@ -57,7 +57,7 @@ module RSpec::Core
57
57
 
58
58
  context "given an example group with no examples" do
59
59
  it "does not pass example_group_started or example_group_finished to formatter" do
60
- formatter = stub("formatter").as_null_object
60
+ formatter = double("formatter").as_null_object
61
61
  formatter.should_not_receive(:example_group_started)
62
62
  formatter.should_not_receive(:example_group_finished)
63
63
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rspec-core
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 2.13.0
5
+ version: 2.13.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Steven Baker
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2013-02-23 00:00:00.000000000 Z
14
+ date: 2013-03-12 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  version_requirements: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 0.4.11
53
+ version: '0.5'
54
54
  none: false
55
55
  prerelease: false
56
56
  name: aruba
@@ -58,23 +58,23 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 0.4.11
61
+ version: '0.5'
62
62
  none: false
63
63
  type: :development
64
64
  - !ruby/object:Gem::Dependency
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - '='
67
+ - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: 4.6.2
69
+ version: '4.6'
70
70
  none: false
71
71
  prerelease: false
72
72
  name: ZenTest
73
73
  requirement: !ruby/object:Gem::Requirement
74
74
  requirements:
75
- - - '='
75
+ - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: 4.6.2
77
+ version: '4.6'
78
78
  none: false
79
79
  type: :development
80
80
  - !ruby/object:Gem::Dependency
@@ -372,7 +372,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
372
372
  version: '0'
373
373
  segments:
374
374
  - 0
375
- hash: 3060570395561359548
375
+ hash: 4384848023819144247
376
376
  none: false
377
377
  required_rubygems_version: !ruby/object:Gem::Requirement
378
378
  requirements:
@@ -381,14 +381,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
381
381
  version: '0'
382
382
  segments:
383
383
  - 0
384
- hash: 3060570395561359548
384
+ hash: 4384848023819144247
385
385
  none: false
386
386
  requirements: []
387
387
  rubyforge_project: rspec
388
388
  rubygems_version: 1.8.24
389
389
  signing_key:
390
390
  specification_version: 3
391
- summary: rspec-core-2.13.0
391
+ summary: rspec-core-2.13.1
392
392
  test_files:
393
393
  - features/Autotest.md
394
394
  - features/README.md