rspec-core 2.13.0 → 2.13.1

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