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.
- data/Changelog.md +35 -2
- data/README.md +14 -13
- data/features/command_line/example_name_option.feature +15 -0
- data/features/helper_methods/modules.feature +3 -3
- data/lib/rspec/core.rb +6 -2
- data/lib/rspec/core/configuration.rb +61 -26
- data/lib/rspec/core/configuration_options.rb +5 -1
- data/lib/rspec/core/deprecation.rb +0 -15
- data/lib/rspec/core/drb_command_line.rb +3 -0
- data/lib/rspec/core/drb_options.rb +3 -1
- data/lib/rspec/core/dsl.rb +4 -2
- data/lib/rspec/core/example.rb +85 -23
- data/lib/rspec/core/example_group.rb +103 -78
- data/lib/rspec/core/hooks.rb +68 -33
- data/lib/rspec/core/let.rb +0 -1
- data/lib/rspec/core/mocking/with_mocha.rb +10 -4
- data/lib/rspec/core/option_parser.rb +3 -2
- data/lib/rspec/core/project_initializer.rb +7 -1
- data/lib/rspec/core/runner.rb +2 -2
- data/lib/rspec/core/shared_context.rb +2 -2
- data/lib/rspec/core/shared_example_group.rb +38 -14
- data/lib/rspec/core/subject.rb +67 -52
- data/lib/rspec/core/version.rb +1 -1
- data/spec/rspec/core/command_line_spec.rb +68 -126
- data/spec/rspec/core/configuration_options_spec.rb +20 -4
- data/spec/rspec/core/configuration_spec.rb +61 -21
- data/spec/rspec/core/drb_command_line_spec.rb +1 -0
- data/spec/rspec/core/drb_options_spec.rb +1 -0
- data/spec/rspec/core/dsl_spec.rb +17 -0
- data/spec/rspec/core/example_group_spec.rb +19 -11
- data/spec/rspec/core/example_spec.rb +34 -0
- data/spec/rspec/core/option_parser_spec.rb +2 -1
- data/spec/rspec/core/shared_example_group_spec.rb +9 -9
- data/spec/rspec/core/subject_spec.rb +14 -0
- data/spec/rspec/core_spec.rb +18 -8
- data/spec/spec_helper.rb +1 -2
- metadata +7 -5
data/Changelog.md
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
### 2.11.0 / 2012-07-07
|
2
|
+
[full changelog](http://github.com/rspec/rspec-core/compare/v2.10.1...v2.11.0)
|
3
|
+
|
4
|
+
Enhancements
|
5
|
+
|
6
|
+
* Support multiple `--example` options. (Daniel Doubrovkine @dblock)
|
7
|
+
* Named subject e.g. `subject(:article) { Article.new }`
|
8
|
+
* see [http://blog.davidchelimsky.net/2012/05/13/spec-smell-explicit-use-of-subject/](http://blog.davidchelimsky.net/2012/05/13/spec-smell-explicit-use-of-subject/)
|
9
|
+
for background.
|
10
|
+
* thanks to Bradley Schaefer for suggesting it and Avdi Grimm for almost
|
11
|
+
suggesting it.
|
12
|
+
* `config.mock_with` and `config.expect_with` yield custom config object to a
|
13
|
+
block if given
|
14
|
+
* aids decoupling from rspec-core's configuation
|
15
|
+
* `include_context` and `include_examples` support a block, which gets eval'd
|
16
|
+
in the current context (vs the nested context generated by `it_behaves_like`).
|
17
|
+
* Add `config.order = 'random'` to the `spec_helper.rb` generated by `rspec
|
18
|
+
--init`.
|
19
|
+
* Delay the loading of DRb (Myron Marston).
|
20
|
+
* Limit monkey patching of `describe` onto just the objects that need it rather
|
21
|
+
than every object in the system (Myron Marston).
|
22
|
+
|
23
|
+
Bug fixes
|
24
|
+
|
25
|
+
* Support alternative path separators. For example, on Windows, you can now do
|
26
|
+
this: `rspec spec\subdir`. (Jarmo Pertman @jarmo)
|
27
|
+
* When an example raises an error and an after or around hook does as
|
28
|
+
well, print out the hook error. Previously, the error was silenced and
|
29
|
+
the user got no feedback about what happened. (Myron Marston)
|
30
|
+
* `--require` and `-I` are merged among different configuration sources (Andy
|
31
|
+
Lindeman)
|
32
|
+
* Delegate to mocha methods instead of aliasing them in mocha adapter.
|
33
|
+
|
1
34
|
### 2.10.1 / 2012-05-19
|
2
35
|
[full changelog](http://github.com/rspec/rspec-core/compare/v2.10.0...v2.10.1)
|
3
36
|
|
@@ -44,8 +77,8 @@ Bug fixes
|
|
44
77
|
over DRb (using spork).
|
45
78
|
* Ensure shared example groups are reset after a run (as example groups are).
|
46
79
|
* Remove `rescue false` from calls to filters represented as Procs
|
47
|
-
* Ensure described_class gets the closest constant (pyromaniac)
|
48
|
-
* In "autorun", don't run the specs in the at_exit hook if there was an
|
80
|
+
* Ensure `described_class` gets the closest constant (pyromaniac)
|
81
|
+
* In "autorun", don't run the specs in the `at_exit` hook if there was an
|
49
82
|
exception (most likely due to a SyntaxError). (sunaku)
|
50
83
|
* Don't extend groups with modules already used to extend ancestor groups.
|
51
84
|
* `its` correctly memoizes nil or false values (Yamada Masaki)
|
data/README.md
CHANGED
@@ -1,21 +1,22 @@
|
|
1
|
-
# rspec-core
|
1
|
+
# rspec-core [![Build Status](https://secure.travis-ci.org/rspec/rspec-core.png?branch=master)](http://travis-ci.org/rspec/rspec-core) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rspec/rspec-core)
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
```
|
3
|
+
rspec-core provides the structure for writing executable examples of how your
|
4
|
+
code should behave, and an `rspec` command with tools to constrain which
|
5
|
+
examples get run and taylor the output.
|
7
6
|
|
8
|
-
|
7
|
+
## install
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
gem install rspec # for rspec-core, rspec-expectations, rspec-mocks
|
10
|
+
gem install rspec-core # for rspec-core only
|
11
|
+
rspec --help
|
12
|
+
|
13
|
+
## basic structure
|
14
|
+
|
15
|
+
RSpec uses the words "describe" and "it" so we can express concepts like a conversation:
|
13
16
|
|
14
17
|
"Describe an order."
|
15
18
|
"It sums the prices of its line items."
|
16
19
|
|
17
|
-
## basic structure
|
18
|
-
|
19
20
|
```ruby
|
20
21
|
describe Order do
|
21
22
|
it "sums the prices of its line items" do
|
@@ -95,8 +96,8 @@ hooks, `let` declarations, and nested groups/contexts.
|
|
95
96
|
|
96
97
|
You can also use the names `shared_context` and `include_context`. These are
|
97
98
|
pretty much the same as `shared_examples` and `include_examples`, providing
|
98
|
-
more accurate naming
|
99
|
-
|
99
|
+
more accurate naming when you share hooks, `let` declarations, helper methods,
|
100
|
+
etc, but no examples.
|
100
101
|
|
101
102
|
## metadata
|
102
103
|
|
@@ -8,6 +8,8 @@ Feature: --example option
|
|
8
8
|
|
9
9
|
This allows you to run a single uniquely named example, all examples with
|
10
10
|
similar names, all the examples in a uniquely named group, etc, etc.
|
11
|
+
|
12
|
+
You can also use the option more than once to specify multiple example matches.
|
11
13
|
|
12
14
|
Background:
|
13
15
|
Given a file named "first_spec.rb" with:
|
@@ -84,3 +86,16 @@ Feature: --example option
|
|
84
86
|
Scenario: Object#method
|
85
87
|
When I run `rspec . --example 'Array#length'`
|
86
88
|
Then the examples should all pass
|
89
|
+
|
90
|
+
Scenario: Multiple applications of example name option
|
91
|
+
When I run `rspec . --example 'first group' --example 'second group' --format d`
|
92
|
+
Then the examples should all pass
|
93
|
+
And the output should contain all of these:
|
94
|
+
|first example in first group|
|
95
|
+
|second example in first group|
|
96
|
+
|first example in second group|
|
97
|
+
|second example in second group|
|
98
|
+
And the output should not contain any of these:
|
99
|
+
|first example in third group|
|
100
|
+
|nested group first example in nested group|
|
101
|
+
|nested group second example in nested group|
|
@@ -33,7 +33,7 @@ Feature: Define helper methods in a module
|
|
33
33
|
end
|
34
34
|
|
35
35
|
describe "an example group" do
|
36
|
-
it "has access the helper methods defined in the module" do
|
36
|
+
it "has access to the helper methods defined in the module" do
|
37
37
|
help.should be(:available)
|
38
38
|
end
|
39
39
|
end
|
@@ -72,7 +72,7 @@ Feature: Define helper methods in a module
|
|
72
72
|
end
|
73
73
|
|
74
74
|
describe "an example group with matching metadata", :foo => :bar do
|
75
|
-
it "has access the helper methods defined in the module" do
|
75
|
+
it "has access to the helper methods defined in the module" do
|
76
76
|
help.should be(:available)
|
77
77
|
end
|
78
78
|
end
|
@@ -130,7 +130,7 @@ Feature: Define helper methods in a module
|
|
130
130
|
describe "an example group with matching include metadata", :include_helpers do
|
131
131
|
puts "In a group not matching the extend filter, help is #{help rescue 'not available'}"
|
132
132
|
|
133
|
-
it "has access the helper methods defined in the module" do
|
133
|
+
it "has access to the helper methods defined in the module" do
|
134
134
|
help.should be(:available)
|
135
135
|
end
|
136
136
|
end
|
data/lib/rspec/core.rb
CHANGED
@@ -11,6 +11,7 @@ else
|
|
11
11
|
end
|
12
12
|
|
13
13
|
require 'set'
|
14
|
+
require 'rbconfig'
|
14
15
|
require_rspec 'core/filter_manager'
|
15
16
|
require_rspec 'core/dsl'
|
16
17
|
require_rspec 'core/extensions'
|
@@ -30,10 +31,8 @@ require_rspec 'core/world'
|
|
30
31
|
require_rspec 'core/configuration'
|
31
32
|
require_rspec 'core/project_initializer'
|
32
33
|
require_rspec 'core/option_parser'
|
33
|
-
require_rspec 'core/drb_options'
|
34
34
|
require_rspec 'core/configuration_options'
|
35
35
|
require_rspec 'core/command_line'
|
36
|
-
require_rspec 'core/drb_command_line'
|
37
36
|
require_rspec 'core/runner'
|
38
37
|
require_rspec 'core/example'
|
39
38
|
require_rspec 'core/shared_example_group'
|
@@ -100,6 +99,11 @@ module RSpec
|
|
100
99
|
world.example_groups.clear
|
101
100
|
end
|
102
101
|
|
102
|
+
# @private
|
103
|
+
def self.windows_os?
|
104
|
+
/mswin|mingw/ === ::RbConfig::CONFIG['host_os']
|
105
|
+
end
|
106
|
+
|
103
107
|
module Core
|
104
108
|
end
|
105
109
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "rbconfig"
|
2
1
|
require 'fileutils'
|
3
2
|
|
4
3
|
module RSpec
|
@@ -278,24 +277,31 @@ MESSAGE
|
|
278
277
|
#
|
279
278
|
# `framework` can be a Symbol or a Module.
|
280
279
|
#
|
281
|
-
# Given any of
|
282
|
-
# framework.
|
280
|
+
# Given any of `:rspec`, `:mocha`, `:flexmock`, or `:rr`, configures the
|
281
|
+
# named framework.
|
283
282
|
#
|
284
|
-
# Given
|
285
|
-
# mocking framework to save a little bit of overhead.
|
283
|
+
# Given `:nothing`, configures no framework. Use this if you don't use
|
284
|
+
# any mocking framework to save a little bit of overhead.
|
286
285
|
#
|
287
286
|
# Given a Module, includes that module in every example group. The module
|
288
287
|
# should adhere to RSpec's mock framework adapter API:
|
289
288
|
#
|
290
|
-
#
|
291
|
-
#
|
289
|
+
# setup_mocks_for_rspec
|
290
|
+
# - called before each example
|
292
291
|
#
|
293
|
-
#
|
294
|
-
#
|
295
|
-
#
|
292
|
+
# verify_mocks_for_rspec
|
293
|
+
# - called after each example. Framework should raise an exception
|
294
|
+
# when expectations fail
|
296
295
|
#
|
297
|
-
#
|
298
|
-
#
|
296
|
+
# teardown_mocks_for_rspec
|
297
|
+
# - called after verify_mocks_for_rspec (even if there are errors)
|
298
|
+
#
|
299
|
+
# If the module responds to `configuration` and `mock_with` receives a block,
|
300
|
+
# it will yield the configuration object to the block e.g.
|
301
|
+
#
|
302
|
+
# config.mock_with OtherMockFrameworkAdapter do |mod_config|
|
303
|
+
# mod_config.custom_setting = true
|
304
|
+
# end
|
299
305
|
def mock_with(framework)
|
300
306
|
framework_module = case framework
|
301
307
|
when Module
|
@@ -324,6 +330,11 @@ MESSAGE
|
|
324
330
|
assert_no_example_groups_defined(:mock_framework)
|
325
331
|
end
|
326
332
|
|
333
|
+
if block_given?
|
334
|
+
raise "#{framework_module} must respond to `configuration` so that mock_with can yield it." unless framework_module.respond_to?(:configuration)
|
335
|
+
yield framework_module.configuration
|
336
|
+
end
|
337
|
+
|
327
338
|
@mock_framework = framework_module
|
328
339
|
end
|
329
340
|
|
@@ -338,16 +349,33 @@ MESSAGE
|
|
338
349
|
expect_with(framework)
|
339
350
|
end
|
340
351
|
|
341
|
-
# Sets the expectation framework module(s)
|
352
|
+
# Sets the expectation framework module(s) to be included in each example
|
353
|
+
# group.
|
354
|
+
#
|
355
|
+
# `frameworks` can be `:rspec`, `:stdlib`, a custom module, or any
|
356
|
+
# combination thereof:
|
357
|
+
#
|
358
|
+
# config.expect_with :rspec
|
359
|
+
# config.expect_with :stdlib
|
360
|
+
# config.expect_with :rspec, :stdlib
|
361
|
+
# config.expect_with OtherExpectationFramework
|
342
362
|
#
|
343
|
-
#
|
363
|
+
# RSpec will translate `:rspec` and `:stdlib` into the appropriate
|
364
|
+
# modules.
|
344
365
|
#
|
345
|
-
#
|
346
|
-
#
|
347
|
-
#
|
366
|
+
# ## Configuration
|
367
|
+
#
|
368
|
+
# If the module responds to `configuration`, `expect_with` will
|
369
|
+
# yield the `configuration` object if given a block:
|
370
|
+
#
|
371
|
+
# config.expect_with OtherExpectationFramework do |custom_config|
|
372
|
+
# custom_config.custom_setting = true
|
373
|
+
# end
|
348
374
|
def expect_with(*frameworks)
|
349
375
|
modules = frameworks.map do |framework|
|
350
376
|
case framework
|
377
|
+
when Module
|
378
|
+
framework
|
351
379
|
when :rspec
|
352
380
|
require 'rspec/expectations'
|
353
381
|
self.expecting_with_rspec = true
|
@@ -364,7 +392,12 @@ MESSAGE
|
|
364
392
|
assert_no_example_groups_defined(:expect_with)
|
365
393
|
end
|
366
394
|
|
367
|
-
|
395
|
+
if block_given?
|
396
|
+
raise "expect_with only accepts a block with a single argument. Call expect_with #{modules.length} times, once with each argument, instead." if modules.length > 1
|
397
|
+
raise "#{modules.first} must respond to `configuration` so that expect_with can yield it." unless modules.first.respond_to?(:configuration)
|
398
|
+
yield modules.first.configuration
|
399
|
+
end
|
400
|
+
|
368
401
|
@expectation_frameworks.push(*modules)
|
369
402
|
end
|
370
403
|
|
@@ -378,10 +411,9 @@ MESSAGE
|
|
378
411
|
end
|
379
412
|
|
380
413
|
def color=(bool)
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
unless ENV['ANSICON']
|
414
|
+
if bool
|
415
|
+
@color = true
|
416
|
+
if RSpec.windows_os? and not ENV['ANSICON']
|
385
417
|
warn "You must use ANSICON 1.31 or later (http://adoxa.110mb.com/ansicon/) to use colour on Windows"
|
386
418
|
@color = false
|
387
419
|
end
|
@@ -429,7 +461,7 @@ EOM
|
|
429
461
|
end
|
430
462
|
|
431
463
|
def full_description=(description)
|
432
|
-
filter_run :full_description =>
|
464
|
+
filter_run :full_description => Regexp.union(*Array(description).map {|d| Regexp.new(d) })
|
433
465
|
end
|
434
466
|
|
435
467
|
# @overload add_formatter(formatter)
|
@@ -504,7 +536,7 @@ EOM
|
|
504
536
|
#
|
505
537
|
# Example:
|
506
538
|
#
|
507
|
-
#
|
539
|
+
# alias_it_behaves_like_to(:it_has_behavior, 'has behavior:')
|
508
540
|
#
|
509
541
|
# allows the user to include a shared example group like:
|
510
542
|
#
|
@@ -519,10 +551,12 @@ EOM
|
|
519
551
|
# Entity
|
520
552
|
# has behavior: sortability
|
521
553
|
# # sortability examples here
|
522
|
-
def
|
523
|
-
RSpec::Core::ExampleGroup.
|
554
|
+
def alias_it_behaves_like_to(new_name, report_label = '')
|
555
|
+
RSpec::Core::ExampleGroup.alias_it_behaves_like_to(new_name, report_label)
|
524
556
|
end
|
525
557
|
|
558
|
+
alias_method :alias_it_should_behave_like_to, :alias_it_behaves_like_to
|
559
|
+
|
526
560
|
# Adds key/value pairs to the `inclusion_filter`. If the
|
527
561
|
# `treat_symbols_as_metadata_keys_with_true_values` config option is set
|
528
562
|
# to true and `args` includes any symbols that are not part of a hash,
|
@@ -770,6 +804,7 @@ EOM
|
|
770
804
|
def get_files_to_run(paths)
|
771
805
|
patterns = pattern.split(",")
|
772
806
|
paths.map do |path|
|
807
|
+
path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
773
808
|
File.directory?(path) ? gather_directories(path, patterns) : extract_location(path)
|
774
809
|
end.flatten
|
775
810
|
end
|
@@ -25,7 +25,9 @@ module RSpec
|
|
25
25
|
|
26
26
|
def parse_options
|
27
27
|
@options ||= extract_filters_from(*all_configs).inject do |merged, pending|
|
28
|
-
merged.merge(pending)
|
28
|
+
merged.merge(pending) { |key, oldval, newval|
|
29
|
+
MERGED_OPTIONS.include?(key) ? oldval + newval : newval
|
30
|
+
}
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -44,6 +46,8 @@ module RSpec
|
|
44
46
|
:line_numbers, :full_description, :full_backtrace, :tty
|
45
47
|
].to_set
|
46
48
|
|
49
|
+
MERGED_OPTIONS = [:requires, :libs].to_set
|
50
|
+
|
47
51
|
def force?(key)
|
48
52
|
!NON_FORCED_OPTIONS.include?(key)
|
49
53
|
end
|
@@ -33,19 +33,4 @@ ADDITIONAL
|
|
33
33
|
send :warn, message
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
37
|
-
# @private
|
38
|
-
class HashWithDeprecationNotice < Hash
|
39
|
-
|
40
|
-
def initialize(method, alternate_method=nil)
|
41
|
-
@method, @alternate_method = method, alternate_method
|
42
|
-
end
|
43
|
-
|
44
|
-
def []=(k,v)
|
45
|
-
RSpec.deprecate(@method, @alternate_method)
|
46
|
-
super(k,v)
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
36
|
end
|
@@ -42,7 +42,9 @@ module RSpec::Core
|
|
42
42
|
# into a regexp when received for the first time (see OptionParser).
|
43
43
|
# Hence, merely grabbing the source of this regexp will retain the
|
44
44
|
# backslashes, so we must remove them.
|
45
|
-
|
45
|
+
@submitted_options[:full_description].each do |description|
|
46
|
+
argv << "--example" << description.source.delete('\\')
|
47
|
+
end
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
data/lib/rspec/core/dsl.rb
CHANGED
@@ -2,7 +2,7 @@ module RSpec
|
|
2
2
|
module Core
|
3
3
|
# Adds the `describe` method to the top-level namespace.
|
4
4
|
module DSL
|
5
|
-
# Generates a subclass of
|
5
|
+
# Generates a subclass of {ExampleGroup}
|
6
6
|
#
|
7
7
|
# ## Examples:
|
8
8
|
#
|
@@ -21,4 +21,6 @@ module RSpec
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
extend RSpec::Core::DSL
|
25
|
+
Module.send(:include, RSpec::Core::DSL)
|
26
|
+
|
data/lib/rspec/core/example.rb
CHANGED
@@ -1,11 +1,37 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
|
-
# Wrapper for an instance of a subclass of
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
3
|
+
# Wrapper for an instance of a subclass of {ExampleGroup}. An instance of
|
4
|
+
# `Example` is returned by the {ExampleGroup#example example} method
|
5
|
+
# exposed to examples, {Hooks#before before} and {Hooks#after after} hooks,
|
6
|
+
# and yielded to {Hooks#around around} hooks.
|
7
|
+
#
|
8
|
+
# Useful for configuring logging and/or taking some action based
|
9
|
+
# on the state of an example's metadata.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# RSpec.configure do |config|
|
14
|
+
# config.before do
|
15
|
+
# log example.description
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# config.after do
|
19
|
+
# log example.description
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# config.around do |ex|
|
23
|
+
# log example.description
|
24
|
+
# ex.run
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# shared_examples "auditable" do
|
29
|
+
# it "does something" do
|
30
|
+
# log "#{example.full_description}: #{auditable.inspect}"
|
31
|
+
# auditable.should do_something
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
9
35
|
# @see ExampleGroup
|
10
36
|
class Example
|
11
37
|
# @private
|
@@ -70,9 +96,9 @@ module RSpec
|
|
70
96
|
alias_method :pending?, :pending
|
71
97
|
|
72
98
|
# @api private
|
99
|
+
# instance_evals the block passed to the constructor in the context of
|
100
|
+
# the instance of {ExampleGroup}.
|
73
101
|
# @param example_group_instance the instance of an ExampleGroup subclass
|
74
|
-
# instance_evals the block submitted to the constructor in the
|
75
|
-
# context of the instance of ExampleGroup
|
76
102
|
def run(example_group_instance, reporter)
|
77
103
|
@example_group_instance = example_group_instance
|
78
104
|
@example_group_instance.example = self
|
@@ -103,16 +129,16 @@ module RSpec
|
|
103
129
|
@example_group_instance = nil
|
104
130
|
|
105
131
|
begin
|
106
|
-
|
132
|
+
assign_generated_description
|
107
133
|
rescue Exception => e
|
108
|
-
set_exception(e)
|
134
|
+
set_exception(e, "while assigning the example description")
|
109
135
|
end
|
110
136
|
end
|
111
137
|
|
112
138
|
finish(reporter)
|
113
139
|
end
|
114
140
|
|
115
|
-
# @private
|
141
|
+
# @api private
|
116
142
|
#
|
117
143
|
# Wraps the example block in a Proc so it can invoked using `run` or
|
118
144
|
# `call` in [around](../Hooks#around-instance_method) hooks.
|
@@ -120,20 +146,39 @@ module RSpec
|
|
120
146
|
proc.extend(Procsy).with(metadata)
|
121
147
|
end
|
122
148
|
|
123
|
-
#
|
149
|
+
# Used to extend a `Proc` with behavior that makes it look something like
|
150
|
+
# an {Example} in an {Hooks#around around} hook.
|
151
|
+
#
|
152
|
+
# @note Procsy, itself, is not a public API, but we're documenting it
|
153
|
+
# here to document how to interact with the object yielded to an
|
154
|
+
# `around` hook.
|
155
|
+
#
|
156
|
+
# @example
|
157
|
+
#
|
158
|
+
# RSpec.configure do |c|
|
159
|
+
# c.around do |ex| # ex is a Proc extended with Procsy
|
160
|
+
# if ex.metadata[:key] == :some_value && some_global_condition
|
161
|
+
# raise "some message"
|
162
|
+
# end
|
163
|
+
# ex.run # run delegates to ex.call
|
164
|
+
# end
|
165
|
+
# end
|
124
166
|
module Procsy
|
167
|
+
# The `metadata` of the {Example} instance.
|
125
168
|
attr_reader :metadata
|
126
169
|
|
127
|
-
# @private
|
170
|
+
# @api private
|
128
171
|
# @param [Proc]
|
129
172
|
# Adds a `run` method to the extended Proc, allowing it to be invoked
|
130
173
|
# in an [around](../Hooks#around-instance_method) hook using either
|
131
174
|
# `run` or `call`.
|
132
|
-
def self.extended(
|
133
|
-
|
175
|
+
def self.extended(proc)
|
176
|
+
# @api public
|
177
|
+
# Foo bar
|
178
|
+
def proc.run; call; end
|
134
179
|
end
|
135
180
|
|
136
|
-
# @private
|
181
|
+
# @api private
|
137
182
|
def with(metadata)
|
138
183
|
@metadata = metadata
|
139
184
|
self
|
@@ -159,7 +204,20 @@ module RSpec
|
|
159
204
|
#
|
160
205
|
# Used internally to set an exception in an after hook, which
|
161
206
|
# captures the exception but doesn't raise it.
|
162
|
-
def set_exception(exception)
|
207
|
+
def set_exception(exception, context=nil)
|
208
|
+
if @exception
|
209
|
+
# An error has already been set; we don't want to override it,
|
210
|
+
# but we also don't want silence the error, so let's print it.
|
211
|
+
msg = <<-EOS
|
212
|
+
|
213
|
+
An error occurred #{context}
|
214
|
+
#{exception.class}: #{exception.message}
|
215
|
+
occurred at #{exception.backtrace.first}
|
216
|
+
|
217
|
+
EOS
|
218
|
+
RSpec.configuration.reporter.message(msg)
|
219
|
+
end
|
220
|
+
|
163
221
|
@exception ||= exception
|
164
222
|
end
|
165
223
|
|
@@ -179,8 +237,8 @@ module RSpec
|
|
179
237
|
end
|
180
238
|
|
181
239
|
# @private
|
182
|
-
def instance_eval_with_rescue(&block)
|
183
|
-
@example_group_instance.instance_eval_with_rescue(&block)
|
240
|
+
def instance_eval_with_rescue(context = nil, &block)
|
241
|
+
@example_group_instance.instance_eval_with_rescue(context, &block)
|
184
242
|
end
|
185
243
|
|
186
244
|
# @private
|
@@ -196,6 +254,8 @@ module RSpec
|
|
196
254
|
else
|
197
255
|
@example_group_class.run_around_each_hooks(self, Example.procsy(metadata, &block))
|
198
256
|
end
|
257
|
+
rescue Exception => e
|
258
|
+
set_exception(e, "in an around(:each) hook")
|
199
259
|
end
|
200
260
|
|
201
261
|
def start(reporter)
|
@@ -235,18 +295,20 @@ module RSpec
|
|
235
295
|
end
|
236
296
|
|
237
297
|
def run_before_each
|
238
|
-
@example_group_instance.setup_mocks_for_rspec
|
298
|
+
@example_group_instance.setup_mocks_for_rspec
|
239
299
|
@example_group_class.run_before_each_hooks(self)
|
240
300
|
end
|
241
301
|
|
242
302
|
def run_after_each
|
243
303
|
@example_group_class.run_after_each_hooks(self)
|
244
|
-
@example_group_instance.verify_mocks_for_rspec
|
304
|
+
@example_group_instance.verify_mocks_for_rspec
|
305
|
+
rescue Exception => e
|
306
|
+
set_exception(e, "in an after(:each) hook")
|
245
307
|
ensure
|
246
|
-
@example_group_instance.teardown_mocks_for_rspec
|
308
|
+
@example_group_instance.teardown_mocks_for_rspec
|
247
309
|
end
|
248
310
|
|
249
|
-
def
|
311
|
+
def assign_generated_description
|
250
312
|
return unless RSpec.configuration.expecting_with_rspec?
|
251
313
|
if metadata[:description].empty? and !pending?
|
252
314
|
metadata[:description] = RSpec::Matchers.generated_description
|