rspec-core 3.1.7 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.yardopts +1 -0
  5. data/Changelog.md +84 -0
  6. data/README.md +10 -1
  7. data/lib/rspec/core.rb +28 -8
  8. data/lib/rspec/core/backport_random.rb +12 -9
  9. data/lib/rspec/core/configuration.rb +350 -112
  10. data/lib/rspec/core/configuration_options.rb +14 -7
  11. data/lib/rspec/core/dsl.rb +7 -4
  12. data/lib/rspec/core/example.rb +86 -50
  13. data/lib/rspec/core/example_group.rb +247 -86
  14. data/lib/rspec/core/filter_manager.rb +38 -93
  15. data/lib/rspec/core/flat_map.rb +4 -4
  16. data/lib/rspec/core/formatters.rb +10 -6
  17. data/lib/rspec/core/formatters/base_formatter.rb +7 -4
  18. data/lib/rspec/core/formatters/base_text_formatter.rb +12 -12
  19. data/lib/rspec/core/formatters/console_codes.rb +8 -7
  20. data/lib/rspec/core/formatters/deprecation_formatter.rb +5 -3
  21. data/lib/rspec/core/formatters/documentation_formatter.rb +10 -4
  22. data/lib/rspec/core/formatters/helpers.rb +6 -4
  23. data/lib/rspec/core/formatters/html_formatter.rb +13 -8
  24. data/lib/rspec/core/formatters/html_printer.rb +26 -10
  25. data/lib/rspec/core/formatters/profile_formatter.rb +10 -7
  26. data/lib/rspec/core/formatters/protocol.rb +27 -18
  27. data/lib/rspec/core/formatters/snippet_extractor.rb +14 -7
  28. data/lib/rspec/core/hooks.rb +252 -211
  29. data/lib/rspec/core/memoized_helpers.rb +16 -16
  30. data/lib/rspec/core/metadata.rb +67 -28
  31. data/lib/rspec/core/metadata_filter.rb +151 -24
  32. data/lib/rspec/core/minitest_assertions_adapter.rb +5 -2
  33. data/lib/rspec/core/mocking_adapters/flexmock.rb +1 -1
  34. data/lib/rspec/core/mocking_adapters/mocha.rb +8 -8
  35. data/lib/rspec/core/notifications.rb +155 -94
  36. data/lib/rspec/core/option_parser.rb +16 -10
  37. data/lib/rspec/core/pending.rb +11 -9
  38. data/lib/rspec/core/project_initializer.rb +1 -1
  39. data/lib/rspec/core/project_initializer/spec/spec_helper.rb +10 -8
  40. data/lib/rspec/core/rake_task.rb +37 -52
  41. data/lib/rspec/core/reporter.rb +30 -7
  42. data/lib/rspec/core/ruby_project.rb +12 -4
  43. data/lib/rspec/core/runner.rb +5 -8
  44. data/lib/rspec/core/sandbox.rb +37 -0
  45. data/lib/rspec/core/shared_example_group.rb +41 -15
  46. data/lib/rspec/core/test_unit_assertions_adapter.rb +3 -3
  47. data/lib/rspec/core/version.rb +1 -1
  48. data/lib/rspec/core/warnings.rb +2 -2
  49. data/lib/rspec/core/world.rb +12 -28
  50. metadata +44 -31
  51. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dc437d7748b2d4e51abc67ecdee4b3222ddbee53
4
- data.tar.gz: fa6c35c84c11393fa3f72dd0bdd8712e31b8ca9e
3
+ metadata.gz: 64add3bc6c923a094fe43e64de951766afb3d546
4
+ data.tar.gz: a6edfdd40534051c51205124394016d6ee23b90c
5
5
  SHA512:
6
- metadata.gz: cc7190d5420cb26fa663b62e4355284b6a869300c118b6ea535d37f5d86bfc8ce9199259f1c1036be7b4193090e03db2e57ef8b7e41574cfb69c239349479a54
7
- data.tar.gz: 0f213b46212dfe8233f1d7466f7e519ef375b6eb1757db8f4a3cdaf630554d43588bf248385eaa79ae0b0d523acb3800493e84e3c31d9c26b1dfc23867db161a
6
+ metadata.gz: ee07178fc56ffde6a07f6f1488acc6a468eda931765714b06f995e073fe539a5468e1b4c31f878761f226fe9223252d078ef43bd2d7c114b03c2352c4baa0600
7
+ data.tar.gz: 370912d590a0243d8f2b532a49e513c87855cfe8ebf3d6d1e6bad896e5011c3fb9fcff932a09fdcefb1d7bef4ebfbf5153f023cac9ca2c2769747c2984d0168f
Binary file
data.tar.gz.sig CHANGED
Binary file
data/.yardopts CHANGED
@@ -3,5 +3,6 @@
3
3
  --markup markdown
4
4
  --default-return void
5
5
  -
6
+ Filtering.md
6
7
  Changelog.md
7
8
  License.txt
@@ -1,3 +1,84 @@
1
+ ### 3.2.0 / 2015-02-03
2
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.7...v3.2.0)
3
+
4
+ Enhancements:
5
+
6
+ * Improve the `inspect` output of example groups. (Mike Dalton, #1687)
7
+ * When rake task fails, only output the command if `verbose` flag is
8
+ set. (Ben Snape, #1704)
9
+ * Add `RSpec.clear_examples` as a clear way to reset examples in between
10
+ spec runs, whilst retaining user configuration. (Alexey Fedorov, #1706)
11
+ * Reduce string allocations when defining and running examples by 70%
12
+ and 50% respectively. (Myron Marston, #1738)
13
+ * Removed dependency on pathname from stdlib. (Sam Phippen, #1703)
14
+ * Improve the message presented when a user hits Ctrl-C.
15
+ (Alex Chaffee #1717, #1742)
16
+ * Improve shared example group inclusion backtrace displayed
17
+ in failed example output so that it works for all methods
18
+ of including shared example groups and shows all inclusion
19
+ locations. (Myron Marston, #1763)
20
+ * Issue seed notification at start (as well as the end) of the reporter
21
+ run. (Arlandis Word, #1761)
22
+ * Improve the documentation of around hooks. (Jim Kingdon, #1772)
23
+ * Support prepending of modules into example groups from config and allow
24
+ filtering based on metadata. (Arlandis Word, #1806)
25
+ * Emit warnings when `:suite` hooks are registered on an example group
26
+ (where it has always been ignored) or are registered with metadata
27
+ (which has always been ignored). (Myron Marston, #1805)
28
+ * Provide a friendly error message when users call RSpec example group
29
+ APIs (e.g. `context`, `describe`, `it`, `let`, `before`, etc) from
30
+ within an example where those APIs are unavailable. (Myron Marston, #1819)
31
+ * Provide a friendly error message when users call RSpec example
32
+ APIs (e.g. `expect`, `double`, `stub_const`, etc) from
33
+ within an example group where those APIs are unavailable.
34
+ (Myron Marston, #1819)
35
+ * Add new `RSpec::Core::Sandbox.sandboxed { }` API that facilitates
36
+ testing RSpec with RSpec, allowing you to define example groups
37
+ and example from within an example without affecting the global
38
+ `RSpec.world` state. (Tyler Ball, 1808)
39
+ * Apply line-number filters only to the files they are scoped to,
40
+ allowing you to mix filtered and unfiltered files. (Myron Marston, #1839)
41
+ * When dumping pending examples, include the failure details so that you
42
+ don't have to un-pend the example to see it. (Myron Marston, #1844)
43
+ * Make `-I` option support multiple values when separated by
44
+ `File::PATH_SEPARATOR`, such as `rspec -I foo:bar`. This matches
45
+ the behavior of Ruby's `-I` option. (Fumiaki Matsushima, #1855).
46
+
47
+ Bug Fixes:
48
+
49
+ * When assigning generated example descriptions, surface errors
50
+ raised by `matcher.description` in the example description.
51
+ (Myron Marston, #1771)
52
+ * Don't consider expectations from `after` hooks when generating
53
+ example descriptions. (Myron Marston, #1771)
54
+ * Don't apply metadata-filtered config hooks to examples in groups
55
+ with matching metadata when those examples override the parent
56
+ metadata value to not match. (Myron Marston, #1796)
57
+ * Fix `config.expect_with :minitest` so that `skip` uses RSpec's
58
+ implementation rather than Minitest's. (Jonathan Rochkind, #1822)
59
+ * Fix `NameError` caused when duplicate example group aliases are defined and
60
+ the DSL is not globally exposed. (Aaron Kromer, #1825)
61
+ * When a shared example defined in an external file fails, use the host
62
+ example group (from a loaded spec file) for the re-run command to
63
+ ensure the command will actually work. (Myron Marston, #1835)
64
+ * Fix location filtering to work properly for examples defined in
65
+ a nested example group within a shared example group defined in
66
+ an external file. (Bradley Schaefer, Xavier Shay, Myron Marston, #1837)
67
+ * When a pending example fails (as expected) due to a mock expectation,
68
+ set `RSpec::Core::Example::ExecutionResult#pending_exception` --
69
+ previously it was not being set but should have been. (Myron Marston, #1844)
70
+ * Fix rake task to work when `rspec-core` is installed in a directory
71
+ containing a space. (Guido Günther, #1845)
72
+ * Fix regression in 3.1 that caused `describe Regexp` to raise errors.
73
+ (Durran Jordan, #1853)
74
+ * Fix regression in 3.x that caused the profile information to be printed
75
+ after the summary. (Max Lincoln, #1857)
76
+ * Apply `--seed` before loading `--require` files so that required files
77
+ can access the provided seed. (Myron Marston, #1745)
78
+ * Handle `RSpec::Core::Formatters::DeprecationFormatter::FileStream` being
79
+ reopened with an IO stream, which sometimes happens with spring.
80
+ (Kevin Mook, #1757)
81
+
1
82
  ### 3.1.7 / 2014-10-11
2
83
  [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.6...v3.1.7)
3
84
 
@@ -456,6 +537,9 @@ Bug Fixes:
456
537
  directory (was broken in beta1). (Jon Rowe)
457
538
  * Prevent RSpec mangling file names that have substrings containing `line_number`
458
539
  or `default_path`. (Matijs van Zuijlen)
540
+ * Fix failure line detection so that it handles relative file paths
541
+ (which can happen when running specs through `ruby` using `rspec/autorun`).
542
+ (Myron Marston, #1829)
459
543
 
460
544
  ### 3.0.0.beta1 / 2013-11-07
461
545
  [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.1...v3.0.0.beta1)
data/README.md CHANGED
@@ -1,4 +1,4 @@
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/github/rspec/rspec-core.png)](https://codeclimate.com/github/rspec/rspec-core)
1
+ # rspec-core [![Build Status](https://secure.travis-ci.org/rspec/rspec-core.svg?branch=master)](http://travis-ci.org/rspec/rspec-core) [![Code Climate](https://codeclimate.com/github/rspec/rspec-core.svg)](https://codeclimate.com/github/rspec/rspec-core)
2
2
 
3
3
  rspec-core provides the structure for writing executable examples of how your
4
4
  code should behave, and an `rspec` command with tools to constrain which
@@ -10,6 +10,15 @@ examples get run and tailor the output.
10
10
  gem install rspec-core # for rspec-core only
11
11
  rspec --help
12
12
 
13
+ Want to run against the `master` branch? You'll need to include the dependent
14
+ RSpec repos as well. Add the following to your `Gemfile`:
15
+
16
+ ```ruby
17
+ %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
18
+ gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => 'master'
19
+ end
20
+ ```
21
+
13
22
  ## basic structure
14
23
 
15
24
  RSpec uses the words "describe" and "it" so we can express concepts like a conversation:
@@ -43,18 +43,38 @@ module RSpec
43
43
 
44
44
  extend RSpec::Core::Warnings
45
45
 
46
- # Used to ensure examples get reloaded between multiple runs in
47
- # the same process.
46
+ class << self
47
+ # Setters for shared global objects
48
+ # @api private
49
+ attr_writer :configuration, :world
50
+ end
51
+
52
+ # Used to ensure examples get reloaded and user configuration gets reset to
53
+ # defaults between multiple runs in the same process.
48
54
  #
49
55
  # Users must invoke this if they want to have the configuration reset when
50
- # they use runner multiple times within the same process.
56
+ # they use the runner multiple times within the same process. Users must deal
57
+ # themselves with re-configuration of RSpec before run.
51
58
  def self.reset
52
59
  @world = nil
53
60
  @configuration = nil
54
61
  end
55
62
 
56
- # Returns the global [Configuration](RSpec/Core/Configuration) object. While you
57
- # _can_ use this method to access the configuration, the more common
63
+ # Used to ensure examples get reloaded between multiple runs in the same
64
+ # process and ensures user configuration is persisted.
65
+ #
66
+ # Users must invoke this if they want to clear all examples but preserve
67
+ # current configuration when they use the runner multiple times within the
68
+ # same process.
69
+ def self.clear_examples
70
+ world.reset
71
+ configuration.reporter.reset
72
+ configuration.start_time = ::RSpec::Core::Time.now
73
+ configuration.reset_filters
74
+ end
75
+
76
+ # Returns the global [Configuration](RSpec/Core/Configuration) object. While
77
+ # you _can_ use this method to access the configuration, the more common
58
78
  # convention is to use [RSpec.configure](RSpec#configure-class_method).
59
79
  #
60
80
  # @example
@@ -116,11 +136,11 @@ module RSpec
116
136
  # A single thread local variable so we don't excessively pollute that
117
137
  # namespace.
118
138
  def self.thread_local_metadata
119
- Thread.current[:_rspec] ||= {}
139
+ Thread.current[:_rspec] ||= { :shared_example_group_inclusions => [] }
120
140
  end
121
141
 
122
142
  # @private
123
- # Internal container for global non-configuration data
143
+ # Internal container for global non-configuration data.
124
144
  def self.world
125
145
  @world ||= RSpec::Core::World.new
126
146
  end
@@ -137,7 +157,7 @@ module RSpec
137
157
  end
138
158
  end
139
159
 
140
- # @private path to executable file
160
+ # @private path to executable file.
141
161
  def self.path_to_executable
142
162
  @path_to_executable ||= File.expand_path('../../../exe/rspec', __FILE__)
143
163
  end
@@ -60,14 +60,14 @@ module RSpec
60
60
  coerce_to(obj, Integer, :to_int)
61
61
  end
62
62
 
63
- # Used internally to make it easy to deal with optional arguments
63
+ # Used internally to make it easy to deal with optional arguments.
64
64
  # (from Rubinius)
65
65
  Undefined = Object.new
66
66
 
67
67
  # @private
68
68
  class Random
69
69
  # @private
70
- # An implementation of Mersenne Twister MT19937 in Ruby
70
+ # An implementation of Mersenne Twister MT19937 in Ruby.
71
71
  class MT19937
72
72
  STATE_SIZE = 624
73
73
  LAST_STATE = STATE_SIZE - 1
@@ -92,9 +92,10 @@ module RSpec
92
92
  end
93
93
 
94
94
  # Seed must be either an Integer (only the first 32 bits will be used)
95
- # or an Array of Integers (of which only the first 32 bits will be used)
95
+ # or an Array of Integers (of which only the first 32 bits will be
96
+ # used).
96
97
  #
97
- # No conversion or type checking is done at this level
98
+ # No conversion or type checking is done at this level.
98
99
  def seed=(seed)
99
100
  case seed
100
101
  when Integer
@@ -129,7 +130,7 @@ module RSpec
129
130
  end
130
131
  end
131
132
 
132
- # Returns a random Integer from the range 0 ... (1 << 32)
133
+ # Returns a random Integer from the range 0 ... (1 << 32).
133
134
  def random_32_bits
134
135
  next_state if @last_read >= LAST_STATE
135
136
  @last_read += 1
@@ -146,12 +147,12 @@ module RSpec
146
147
  # No argument checking is done here either.
147
148
 
148
149
  FLOAT_FACTOR = 1.0/9007199254740992.0
149
- # generates a random number on [0,1) with 53-bit resolution
150
+ # Generates a random number on [0, 1) with 53-bit resolution.
150
151
  def random_float
151
152
  ((random_32_bits >> 5) * 67108864.0 + (random_32_bits >> 6)) * FLOAT_FACTOR;
152
153
  end
153
154
 
154
- # Returns an integer within 0...upto
155
+ # Returns an integer within 0...upto.
155
156
  def random_integer(upto)
156
157
  n = upto - 1
157
158
  nb_full_32 = 0
@@ -202,7 +203,8 @@ module RSpec
202
203
  end
203
204
  end
204
205
 
205
- # Convert an Integer seed of arbitrary size to either a single 32 bit integer, or an Array of 32 bit integers
206
+ # Convert an Integer seed of arbitrary size to either a single 32 bit
207
+ # integer, or an Array of 32 bit integers.
206
208
  def self.convert_seed(seed)
207
209
  seed = seed.abs
208
210
  long_values = []
@@ -211,7 +213,8 @@ module RSpec
211
213
  seed >>= 32
212
214
  end until seed == 0
213
215
 
214
- long_values.pop if long_values[-1] == 1 && long_values.size > 1 # Done to allow any kind of sequence of integers
216
+ # Done to allow any kind of sequence of integers.
217
+ long_values.pop if long_values[-1] == 1 && long_values.size > 1
215
218
 
216
219
  long_values.size > 1 ? long_values : long_values.first
217
220
  end
@@ -32,15 +32,23 @@ module RSpec
32
32
  class Configuration
33
33
  include RSpec::Core::Hooks
34
34
 
35
+ # Module that holds `attr_reader` declarations. It's in a separate
36
+ # module to allow us to override those methods and use `super`.
37
+ # @private
38
+ Readers = Module.new
39
+ include Readers
40
+
35
41
  # @private
36
42
  class MustBeConfiguredBeforeExampleGroupsError < StandardError; end
37
43
 
38
44
  # @private
39
45
  def self.define_reader(name)
40
- define_method(name) do
41
- variable = instance_variable_defined?("@#{name}") ? instance_variable_get("@#{name}") : nil
42
- value_for(name, variable)
46
+ Readers.class_eval do
47
+ remove_method name if method_defined?(name)
48
+ attr_reader name
43
49
  end
50
+
51
+ define_method(name) { value_for(name) { super() } }
44
52
  end
45
53
 
46
54
  # @private
@@ -71,7 +79,7 @@ module RSpec
71
79
 
72
80
  # @private
73
81
  #
74
- # As `add_setting` but only add the reader
82
+ # As `add_setting` but only add the reader.
75
83
  def self.add_read_only_setting(name, opts={})
76
84
  raise "Use the instance add_setting method if you want to set a default" if opts.key?(:default)
77
85
  define_reader name
@@ -90,8 +98,8 @@ module RSpec
90
98
  # `"spec"`). Allows you to just type `rspec` instead of `rspec spec` to
91
99
  # run all the examples in the `spec` directory.
92
100
  #
93
- # Note: Other scripts invoking `rspec` indirectly will ignore this
94
- # setting.
101
+ # @note Other scripts invoking `rspec` indirectly will ignore this
102
+ # setting.
95
103
  add_setting :default_path
96
104
 
97
105
  # @macro add_setting
@@ -160,11 +168,12 @@ module RSpec
160
168
  add_setting :failure_exit_code
161
169
 
162
170
  # @macro define_reader
163
- # Indicates files configured to be required
171
+ # Indicates files configured to be required.
164
172
  define_reader :requires
165
173
 
166
174
  # @macro define_reader
167
- # Returns dirs that have been prepended to the load path by the `-I` command line option
175
+ # Returns dirs that have been prepended to the load path by the `-I`
176
+ # command line option.
168
177
  define_reader :libs
169
178
 
170
179
  # @macro add_setting
@@ -172,7 +181,7 @@ module RSpec
172
181
  # Default: `$stdout`.
173
182
  define_reader :output_stream
174
183
 
175
- # Set the output stream for reporter
184
+ # Set the output stream for reporter.
176
185
  # @attr value [IO] value for output, defaults to $stdout
177
186
  def output_stream=(value)
178
187
  if @reporter && !value.equal?(@output_stream)
@@ -186,20 +195,20 @@ module RSpec
186
195
  end
187
196
 
188
197
  # @macro define_reader
189
- # Load files matching this pattern (default: `'**{,/*/**}/*_spec.rb'`)
198
+ # Load files matching this pattern (default: `'**{,/*/**}/*_spec.rb'`).
190
199
  define_reader :pattern
191
200
 
192
- # Set pattern to match files to load
201
+ # Set pattern to match files to load.
193
202
  # @attr value [String] the filename pattern to filter spec files by
194
203
  def pattern=(value)
195
204
  update_pattern_attr :pattern, value
196
205
  end
197
206
 
198
207
  # @macro define_reader
199
- # Exclude files matching this pattern
208
+ # Exclude files matching this pattern.
200
209
  define_reader :exclude_pattern
201
210
 
202
- # Set pattern to match files to exclude
211
+ # Set pattern to match files to exclude.
203
212
  # @attr value [String] the filename pattern to exclude spec files by
204
213
  def exclude_pattern=(value)
205
214
  update_pattern_attr :exclude_pattern, value
@@ -211,84 +220,93 @@ module RSpec
211
220
  add_setting :profile_examples
212
221
 
213
222
  # @macro add_setting
214
- # Run all examples if none match the configured filters (default: `false`).
223
+ # Run all examples if none match the configured filters
224
+ # (default: `false`).
215
225
  add_setting :run_all_when_everything_filtered
216
226
 
217
227
  # @macro add_setting
218
228
  # Color to use to indicate success.
219
229
  # @param color [Symbol] defaults to `:green` but can be set to one of the
220
- # following: `[:black, :white, :red, :green, :yellow,
221
- # :blue, :magenta, :cyan]`
230
+ # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
231
+ # :cyan]`
222
232
  add_setting :success_color
223
233
 
224
234
  # @macro add_setting
225
235
  # Color to use to print pending examples.
226
236
  # @param color [Symbol] defaults to `:yellow` but can be set to one of the
227
- # following: `[:black, :white, :red, :green, :yellow,
228
- # :blue, :magenta, :cyan]`
237
+ # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
238
+ # :cyan]`
229
239
  add_setting :pending_color
230
240
 
231
241
  # @macro add_setting
232
242
  # Color to use to indicate failure.
233
243
  # @param color [Symbol] defaults to `:red` but can be set to one of the
234
- # following: `[:black, :white, :red, :green, :yellow,
235
- # :blue, :magenta, :cyan]`
244
+ # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
245
+ # :cyan]`
236
246
  add_setting :failure_color
237
247
 
238
248
  # @macro add_setting
239
249
  # The default output color.
240
250
  # @param color [Symbol] defaults to `:white` but can be set to one of the
241
- # following:`[:black, :white, :red, :green, :yellow,
242
- # :blue, :magenta, :cyan]`
251
+ # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
252
+ # :cyan]`
243
253
  add_setting :default_color
244
254
 
245
255
  # @macro add_setting
246
256
  # Color used when a pending example is fixed.
247
257
  # @param color [Symbol] defaults to `:blue` but can be set to one of the
248
- # following: `[:black, :white, :red, :green, :yellow,
249
- # :blue, :magenta, :cyan]`
258
+ # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
259
+ # :cyan]`
250
260
  add_setting :fixed_color
251
261
 
252
262
  # @macro add_setting
253
263
  # Color used to print details.
254
264
  # @param color [Symbol] defaults to `:cyan` but can be set to one of the
255
- # following: `[:black, :white, :red, :green, :yellow,
256
- # :blue, :magenta, :cyan]`
265
+ # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
266
+ # :cyan]`
257
267
  add_setting :detail_color
258
268
 
259
269
  # Deprecated. This config option was added in RSpec 2 to pave the way
260
270
  # for this being the default behavior in RSpec 3. Now this option is
261
271
  # a no-op.
262
272
  def treat_symbols_as_metadata_keys_with_true_values=(_value)
263
- RSpec.deprecate("RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=",
264
- :message => "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values= " \
265
- "is deprecated, it is now set to true as default and setting it to false has no effect.")
273
+ RSpec.deprecate(
274
+ "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=",
275
+ :message => "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values= " \
276
+ "is deprecated, it is now set to true as default and " \
277
+ "setting it to false has no effect."
278
+ )
266
279
  end
267
280
 
268
- # Record the start time of the spec suite to measure load time
281
+ # Record the start time of the spec suite to measure load time.
269
282
  add_setting :start_time
270
283
 
271
284
  # @private
272
285
  add_setting :tty
273
286
  # @private
274
- add_setting :include_or_extend_modules
275
- # @private
276
287
  attr_writer :files_to_run
277
288
  # @private
278
- add_setting :expecting_with_rspec
279
- # @private
280
289
  attr_accessor :filter_manager
281
290
  # @private
282
- attr_reader :backtrace_formatter, :ordering_manager
291
+ attr_accessor :static_config_filter_manager
292
+ # @private
293
+ attr_reader :backtrace_formatter, :ordering_manager, :loaded_spec_files
283
294
 
284
295
  def initialize
285
296
  # rubocop:disable Style/GlobalVars
286
297
  @start_time = $_rspec_core_load_started_at || ::RSpec::Core::Time.now
287
298
  # rubocop:enable Style/GlobalVars
288
299
  @expectation_frameworks = []
289
- @include_or_extend_modules = []
300
+ @include_modules = FilterableItemRepository::QueryOptimized.new(:any?)
301
+ @extend_modules = FilterableItemRepository::QueryOptimized.new(:any?)
302
+ @prepend_modules = FilterableItemRepository::QueryOptimized.new(:any?)
303
+
304
+ @before_suite_hooks = []
305
+ @after_suite_hooks = []
306
+
290
307
  @mock_framework = nil
291
308
  @files_or_directories_to_run = []
309
+ @loaded_spec_files = Set.new
292
310
  @color = false
293
311
  @pattern = '**{,/*/**}/*_spec.rb'
294
312
  @exclude_pattern = ''
@@ -303,6 +321,7 @@ module RSpec
303
321
  @reporter = nil
304
322
  @reporter_buffer = nil
305
323
  @filter_manager = FilterManager.new
324
+ @static_config_filter_manager = FilterManager.new
306
325
  @ordering_manager = Ordering::ConfigurationManager.new
307
326
  @preferred_options = {}
308
327
  @failure_color = :red
@@ -314,7 +333,7 @@ module RSpec
314
333
  @profile_examples = false
315
334
  @requires = []
316
335
  @libs = []
317
- @derived_metadata_blocks = []
336
+ @derived_metadata_blocks = FilterableItemRepository::QueryOptimized.new(:any?)
318
337
  end
319
338
 
320
339
  # @private
@@ -332,18 +351,29 @@ module RSpec
332
351
  @formatter_loader = nil
333
352
  end
334
353
 
354
+ # @private
355
+ def reset_filters
356
+ self.filter_manager = FilterManager.new
357
+ filter_manager.include_only(
358
+ Metadata.deep_hash_dup(static_config_filter_manager.inclusions.rules)
359
+ )
360
+ filter_manager.exclude_only(
361
+ Metadata.deep_hash_dup(static_config_filter_manager.exclusions.rules)
362
+ )
363
+ end
364
+
335
365
  # @overload add_setting(name)
336
366
  # @overload add_setting(name, opts)
337
367
  # @option opts [Symbol] :default
338
368
  #
339
- # set a default value for the generated getter and predicate methods:
369
+ # Set a default value for the generated getter and predicate methods:
340
370
  #
341
371
  # add_setting(:foo, :default => "default value")
342
372
  #
343
373
  # @option opts [Symbol] :alias_with
344
374
  #
345
- # Use `:alias_with` to alias the setter, getter, and predicate to another
346
- # name, or names:
375
+ # Use `:alias_with` to alias the setter, getter, and predicate to
376
+ # another name, or names:
347
377
  #
348
378
  # add_setting(:foo, :alias_with => :bar)
349
379
  # add_setting(:foo, :alias_with => [:bar, :baz])
@@ -366,7 +396,7 @@ module RSpec
366
396
  #
367
397
  # RSpec.configuration.foo=(value)
368
398
  # RSpec.configuration.foo
369
- # RSpec.configuration.foo? # returns true if foo returns anything but nil or false
399
+ # RSpec.configuration.foo? # Returns true if foo returns anything but nil or false.
370
400
  def add_setting(name, opts={})
371
401
  default = opts.delete(:default)
372
402
  (class << self; self; end).class_exec do
@@ -375,7 +405,7 @@ module RSpec
375
405
  __send__("#{name}=", default) if default
376
406
  end
377
407
 
378
- # Returns the configured mock framework adapter module
408
+ # Returns the configured mock framework adapter module.
379
409
  def mock_framework
380
410
  if @mock_framework.nil?
381
411
  begin
@@ -387,7 +417,7 @@ module RSpec
387
417
  @mock_framework
388
418
  end
389
419
 
390
- # Delegates to mock_framework=(framework)
420
+ # Delegates to mock_framework=(framework).
391
421
  def mock_framework=(framework)
392
422
  mock_with framework
393
423
  end
@@ -395,19 +425,19 @@ module RSpec
395
425
  # Regexps used to exclude lines from backtraces.
396
426
  #
397
427
  # Excludes lines from ruby (and jruby) source, installed gems, anything
398
- # in any "bin" directory, and any of the rspec libs (outside gem
428
+ # in any "bin" directory, and any of the RSpec libs (outside gem
399
429
  # installs) by default.
400
430
  #
401
431
  # You can modify the list via the getter, or replace it with the setter.
402
432
  #
403
433
  # To override this behaviour and display a full backtrace, use
404
- # `--backtrace`on the command line, in a `.rspec` file, or in the
434
+ # `--backtrace` on the command line, in a `.rspec` file, or in the
405
435
  # `rspec_options` attribute of RSpec's rake task.
406
436
  def backtrace_exclusion_patterns
407
437
  @backtrace_formatter.exclusion_patterns
408
438
  end
409
439
 
410
- # Set regular expressions used to exclude lines in backtrace
440
+ # Set regular expressions used to exclude lines in backtrace.
411
441
  # @param patterns [Regexp] set the backtrace exlusion pattern
412
442
  def backtrace_exclusion_patterns=(patterns)
413
443
  @backtrace_formatter.exclusion_patterns = patterns
@@ -425,7 +455,7 @@ module RSpec
425
455
  @backtrace_formatter.inclusion_patterns
426
456
  end
427
457
 
428
- # Set regular expressions used to include lines in backtrace
458
+ # Set regular expressions used to include lines in backtrace.
429
459
  # @attr patterns [Regexp] set backtrace_formatter inclusion_patterns
430
460
  def backtrace_inclusion_patterns=(patterns)
431
461
  @backtrace_formatter.inclusion_patterns = patterns
@@ -485,8 +515,8 @@ module RSpec
485
515
  # teardown_mocks_for_rspec
486
516
  # - called after verify_mocks_for_rspec (even if there are errors)
487
517
  #
488
- # If the module responds to `configuration` and `mock_with` receives a block,
489
- # it will yield the configuration object to the block e.g.
518
+ # If the module responds to `configuration` and `mock_with` receives a
519
+ # block, it will yield the configuration object to the block e.g.
490
520
  #
491
521
  # config.mock_with OtherMockFrameworkAdapter do |mod_config|
492
522
  # mod_config.custom_setting = true
@@ -515,7 +545,8 @@ module RSpec
515
545
  end
516
546
 
517
547
  if block_given?
518
- raise "#{framework_module} must respond to `configuration` so that mock_with can yield it." unless framework_module.respond_to?(:configuration)
548
+ raise "#{framework_module} must respond to `configuration` so that " \
549
+ "mock_with can yield it." unless framework_module.respond_to?(:configuration)
519
550
  yield framework_module.configuration
520
551
  end
521
552
 
@@ -534,7 +565,7 @@ module RSpec
534
565
  @expectation_frameworks
535
566
  end
536
567
 
537
- # Delegates to expect_with(framework)
568
+ # Delegates to expect_with(framework).
538
569
  def expectation_framework=(framework)
539
570
  expect_with(framework)
540
571
  end
@@ -569,7 +600,6 @@ module RSpec
569
600
  framework
570
601
  when :rspec
571
602
  require 'rspec/expectations'
572
- self.expecting_with_rspec = true
573
603
  ::RSpec::Matchers
574
604
  when :test_unit
575
605
  require 'rspec/core/test_unit_assertions_adapter'
@@ -587,21 +617,24 @@ module RSpec
587
617
  end
588
618
 
589
619
  if block_given?
590
- 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
591
- raise "#{modules.first} must respond to `configuration` so that expect_with can yield it." unless modules.first.respond_to?(:configuration)
620
+ raise "expect_with only accepts a block with a single argument. " \
621
+ "Call expect_with #{modules.length} times, " \
622
+ "once with each argument, instead." if modules.length > 1
623
+ raise "#{modules.first} must respond to `configuration` so that " \
624
+ "expect_with can yield it." unless modules.first.respond_to?(:configuration)
592
625
  yield modules.first.configuration
593
626
  end
594
627
 
595
628
  @expectation_frameworks.push(*modules)
596
629
  end
597
630
 
598
- # Check if full backtrace is enabled
631
+ # Check if full backtrace is enabled.
599
632
  # @return [Boolean] is full backtrace enabled
600
633
  def full_backtrace?
601
634
  @backtrace_formatter.full_backtrace?
602
635
  end
603
636
 
604
- # Toggle full backtrace
637
+ # Toggle full backtrace.
605
638
  # @attr true_or_false [Boolean] toggle full backtrace display
606
639
  def full_backtrace=(true_or_false)
607
640
  @backtrace_formatter.full_backtrace = true_or_false
@@ -613,10 +646,10 @@ module RSpec
613
646
  # @see color_enabled?
614
647
  # @return [Boolean]
615
648
  def color
616
- value_for(:color, @color)
649
+ value_for(:color) { @color }
617
650
  end
618
651
 
619
- # Check if color is enabled for a particular output
652
+ # Check if color is enabled for a particular output.
620
653
  # @param output [IO] an output stream to use, defaults to the current
621
654
  # `output_stream`
622
655
  # @return [Boolean]
@@ -624,13 +657,15 @@ module RSpec
624
657
  output_to_tty?(output) && color
625
658
  end
626
659
 
627
- # Toggle output color
660
+ # Toggle output color.
628
661
  # @attr true_or_false [Boolean] toggle color enabled
629
662
  def color=(true_or_false)
630
663
  return unless true_or_false
631
664
 
632
- if RSpec.world.windows_os? && !ENV['ANSICON']
633
- RSpec.warning "You must use ANSICON 1.31 or later (http://adoxa.3eeweb.com/ansicon/) to use colour on Windows"
665
+ if RSpec::Support::OS.windows? && !ENV['ANSICON']
666
+ RSpec.warning "You must use ANSICON 1.31 or later " \
667
+ "(http://adoxa.3eeweb.com/ansicon/) to use colour " \
668
+ "on Windows"
634
669
  @color = false
635
670
  else
636
671
  @color = true
@@ -743,10 +778,10 @@ module RSpec
743
778
 
744
779
  # @api private
745
780
  #
746
- # Defaults `profile_examples` to 10 examples when `@profile_examples` is `true`.
747
- #
781
+ # Defaults `profile_examples` to 10 examples when `@profile_examples` is
782
+ # `true`.
748
783
  def profile_examples
749
- profile = value_for(:profile_examples, @profile_examples)
784
+ profile = value_for(:profile_examples) { @profile_examples }
750
785
  if profile && !profile.is_a?(Integer)
751
786
  10
752
787
  else
@@ -762,7 +797,7 @@ module RSpec
762
797
  @files_to_run = nil
763
798
  end
764
799
 
765
- # The spec files RSpec will run
800
+ # The spec files RSpec will run.
766
801
  # @return [Array] specified files about to run
767
802
  def files_to_run
768
803
  @files_to_run ||= get_files_to_run(@files_or_directories_to_run)
@@ -776,8 +811,8 @@ module RSpec
776
811
  # @note The specific example alias below (`pending`) is already
777
812
  # defined for you.
778
813
  # @note Use with caution. This extends the language used in your
779
- # specs, but does not add any additional documentation. We use this
780
- # in rspec to define methods like `focus` and `xit`, but we also add
814
+ # specs, but does not add any additional documentation. We use this
815
+ # in RSpec to define methods like `focus` and `xit`, but we also add
781
816
  # docs for those methods.
782
817
  #
783
818
  # @example
@@ -860,8 +895,8 @@ module RSpec
860
895
  # # ...sortability examples here
861
896
  #
862
897
  # @note Use with caution. This extends the language used in your
863
- # specs, but does not add any additional documentation. We use this
864
- # in rspec to define `it_should_behave_like` (for backward
898
+ # specs, but does not add any additional documentation. We use this
899
+ # in RSpec to define `it_should_behave_like` (for backward
865
900
  # compatibility), but we also add docs for that method.
866
901
  def alias_it_behaves_like_to(new_name, report_label='')
867
902
  RSpec::Core::ExampleGroup.define_nested_shared_group_method(new_name, report_label)
@@ -878,28 +913,30 @@ module RSpec
878
913
  # or config files (e.g. `.rspec`).
879
914
  #
880
915
  # @example
881
- # # given this declaration
916
+ # # Given this declaration.
882
917
  # describe "something", :foo => 'bar' do
883
918
  # # ...
884
919
  # end
885
920
  #
886
- # # any of the following will include that group
921
+ # # Any of the following will include that group.
887
922
  # config.filter_run_including :foo => 'bar'
888
923
  # config.filter_run_including :foo => /^ba/
889
924
  # config.filter_run_including :foo => lambda {|v| v == 'bar'}
890
925
  # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
891
926
  #
892
- # # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
927
+ # # Given a proc with an arity of 1, the lambda is passed the value
928
+ # # related to the key, e.g.
893
929
  # config.filter_run_including :foo => lambda {|v| v == 'bar'}
894
930
  #
895
- # # given a proc with an arity of 2, the lambda is passed the value related to the key,
896
- # # and the metadata itself e.g.
931
+ # # Given a proc with an arity of 2, the lambda is passed the value
932
+ # # related to the key, and the metadata itself e.g.
897
933
  # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
898
934
  #
899
935
  # filter_run_including :foo # same as filter_run_including :foo => true
900
936
  def filter_run_including(*args)
901
937
  meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
902
938
  filter_manager.include_with_low_priority meta
939
+ static_config_filter_manager.include_with_low_priority Metadata.deep_hash_dup(meta)
903
940
  end
904
941
 
905
942
  alias_method :filter_run, :filter_run_including
@@ -936,28 +973,30 @@ module RSpec
936
973
  # or config files (e.g. `.rspec`).
937
974
  #
938
975
  # @example
939
- # # given this declaration
976
+ # # Given this declaration.
940
977
  # describe "something", :foo => 'bar' do
941
978
  # # ...
942
979
  # end
943
980
  #
944
- # # any of the following will exclude that group
981
+ # # Any of the following will exclude that group.
945
982
  # config.filter_run_excluding :foo => 'bar'
946
983
  # config.filter_run_excluding :foo => /^ba/
947
984
  # config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
948
985
  # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
949
986
  #
950
- # # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
987
+ # # Given a proc with an arity of 1, the lambda is passed the value
988
+ # # related to the key, e.g.
951
989
  # config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
952
990
  #
953
- # # given a proc with an arity of 2, the lambda is passed the value related to the key,
954
- # # and the metadata itself e.g.
991
+ # # Given a proc with an arity of 2, the lambda is passed the value
992
+ # # related to the key, and the metadata itself e.g.
955
993
  # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
956
994
  #
957
995
  # filter_run_excluding :foo # same as filter_run_excluding :foo => true
958
996
  def filter_run_excluding(*args)
959
997
  meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
960
998
  filter_manager.exclude_with_low_priority meta
999
+ static_config_filter_manager.exclude_with_low_priority Metadata.deep_hash_dup(meta)
961
1000
  end
962
1001
 
963
1002
  # Clears and reassigns the `exclusion_filter`. Set to `nil` if you don't
@@ -979,8 +1018,8 @@ module RSpec
979
1018
  end
980
1019
 
981
1020
  # Tells RSpec to include `mod` in example groups. Methods defined in
982
- # `mod` are exposed to examples (not example groups). Use `filters` to
983
- # constrain the groups in which to include the module.
1021
+ # `mod` are exposed to examples (not example groups). Use `filters` to
1022
+ # constrain the groups or examples in which to include the module.
984
1023
  #
985
1024
  # @example
986
1025
  #
@@ -1009,14 +1048,22 @@ module RSpec
1009
1048
  # end
1010
1049
  # end
1011
1050
  #
1051
+ # @note Filtered module inclusions can also be applied to
1052
+ # individual examples that have matching metadata. Just like
1053
+ # Ruby's object model is that every object has a singleton class
1054
+ # which has only a single instance, RSpec's model is that every
1055
+ # example has a singleton example group containing just the one
1056
+ # example.
1057
+ #
1012
1058
  # @see #extend
1059
+ # @see #prepend
1013
1060
  def include(mod, *filters)
1014
1061
  meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1015
- include_or_extend_modules << [:include, mod, meta]
1062
+ @include_modules.append(mod, meta)
1016
1063
  end
1017
1064
 
1018
- # Tells RSpec to extend example groups with `mod`. Methods defined in
1019
- # `mod` are exposed to example groups (not examples). Use `filters` to
1065
+ # Tells RSpec to extend example groups with `mod`. Methods defined in
1066
+ # `mod` are exposed to example groups (not examples). Use `filters` to
1020
1067
  # constrain the groups to extend.
1021
1068
  #
1022
1069
  # Similar to `include`, but behavior is added to example groups, which
@@ -1044,25 +1091,87 @@ module RSpec
1044
1091
  # end
1045
1092
  #
1046
1093
  # @see #include
1094
+ # @see #prepend
1047
1095
  def extend(mod, *filters)
1048
1096
  meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1049
- include_or_extend_modules << [:extend, mod, meta]
1097
+ @extend_modules.append(mod, meta)
1098
+ end
1099
+
1100
+ if RSpec::Support::RubyFeatures.module_prepends_supported?
1101
+ # Tells RSpec to prepend example groups with `mod`. Methods defined in
1102
+ # `mod` are exposed to examples (not example groups). Use `filters` to
1103
+ # constrain the groups in which to prepend the module.
1104
+ #
1105
+ # Similar to `include`, but module is included before the example group's class
1106
+ # in the ancestor chain.
1107
+ #
1108
+ # @example
1109
+ #
1110
+ # module OverrideMod
1111
+ # def override_me
1112
+ # "overridden"
1113
+ # end
1114
+ # end
1115
+ #
1116
+ # RSpec.configure do |config|
1117
+ # config.prepend(OverrideMod, :method => :prepend)
1118
+ # end
1119
+ #
1120
+ # describe "overriding example's class", :method => :prepend do
1121
+ # it "finds the user" do
1122
+ # self.class.class_eval do
1123
+ # def override_me
1124
+ # end
1125
+ # end
1126
+ # override_me # => "overridden"
1127
+ # # ...
1128
+ # end
1129
+ # end
1130
+ #
1131
+ # @see #include
1132
+ # @see #extend
1133
+ def prepend(mod, *filters)
1134
+ meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1135
+ @prepend_modules.append(mod, meta)
1136
+ end
1050
1137
  end
1051
1138
 
1052
1139
  # @private
1053
1140
  #
1054
- # Used internally to extend a group with modules using `include` and/or
1141
+ # Used internally to extend a group with modules using `include`, `prepend` and/or
1055
1142
  # `extend`.
1056
1143
  def configure_group(group)
1057
- include_or_extend_modules.each do |include_or_extend, mod, filters|
1058
- next unless filters.empty? || group.any_apply?(filters)
1059
- __send__("safe_#{include_or_extend}", mod, group)
1144
+ configure_group_with group, @include_modules, :safe_include
1145
+ configure_group_with group, @extend_modules, :safe_extend
1146
+ configure_group_with group, @prepend_modules, :safe_prepend
1147
+ end
1148
+
1149
+ # @private
1150
+ def configure_group_with(group, module_list, application_method)
1151
+ module_list.items_for(group.metadata).each do |mod|
1152
+ __send__(application_method, mod, group)
1060
1153
  end
1061
1154
  end
1062
1155
 
1063
1156
  # @private
1064
- def safe_include(mod, host)
1065
- host.__send__(:include, mod) unless host < mod
1157
+ #
1158
+ # Used internally to extend the singleton class of a single example's
1159
+ # example group instance with modules using `include` and/or `extend`.
1160
+ def configure_example(example)
1161
+ # We replace the metadata so that SharedExampleGroupModule#included
1162
+ # has access to the example's metadata[:location].
1163
+ example.example_group_instance.singleton_class.with_replaced_metadata(example.metadata) do
1164
+ @include_modules.items_for(example.metadata).each do |mod|
1165
+ safe_include(mod, example.example_group_instance.singleton_class)
1166
+ end
1167
+ end
1168
+ end
1169
+
1170
+ if RSpec::Support::RubyFeatures.module_prepends_supported?
1171
+ # @private
1172
+ def safe_prepend(mod, host)
1173
+ host.__send__(:prepend, mod) unless host < mod
1174
+ end
1066
1175
  end
1067
1176
 
1068
1177
  # @private
@@ -1075,11 +1184,21 @@ module RSpec
1075
1184
 
1076
1185
  # @private
1077
1186
  if RUBY_VERSION.to_f >= 1.9
1187
+ # @private
1188
+ def safe_include(mod, host)
1189
+ host.__send__(:include, mod) unless host < mod
1190
+ end
1191
+
1078
1192
  # @private
1079
1193
  def safe_extend(mod, host)
1080
1194
  host.extend(mod) unless host.singleton_class < mod
1081
1195
  end
1082
1196
  else
1197
+ # @private
1198
+ def safe_include(mod, host)
1199
+ host.__send__(:include, mod) unless host.included_modules.include?(mod)
1200
+ end
1201
+
1083
1202
  # @private
1084
1203
  def safe_extend(mod, host)
1085
1204
  host.extend(mod) unless (class << host; self; end).included_modules.include?(mod)
@@ -1102,7 +1221,12 @@ module RSpec
1102
1221
 
1103
1222
  # @private
1104
1223
  def load_spec_files
1105
- files_to_run.uniq.each { |f| load File.expand_path(f) }
1224
+ files_to_run.uniq.each do |f|
1225
+ file = File.expand_path(f)
1226
+ load file
1227
+ loaded_spec_files << file
1228
+ end
1229
+
1106
1230
  @spec_files_loaded = true
1107
1231
  end
1108
1232
 
@@ -1112,7 +1236,8 @@ module RSpec
1112
1236
  # Formats the docstring output using the block provided.
1113
1237
  #
1114
1238
  # @example
1115
- # # This will strip the descriptions of both examples and example groups.
1239
+ # # This will strip the descriptions of both examples and example
1240
+ # # groups.
1116
1241
  # RSpec.configure do |config|
1117
1242
  # config.format_docstrings { |s| s.strip }
1118
1243
  # end
@@ -1157,7 +1282,8 @@ module RSpec
1157
1282
 
1158
1283
  # @macro delegate_to_ordering_manager
1159
1284
  #
1160
- # Sets the default global order and, if order is `'rand:<seed>'`, also sets the seed.
1285
+ # Sets the default global order and, if order is `'rand:<seed>'`, also
1286
+ # sets the seed.
1161
1287
  delegate_to_ordering_manager :order=
1162
1288
 
1163
1289
  # @macro delegate_to_ordering_manager
@@ -1167,8 +1293,10 @@ module RSpec
1167
1293
  #
1168
1294
  # @param name [Symbol] The name of the ordering.
1169
1295
  # @yield Block that will order the given examples or example groups
1170
- # @yieldparam list [Array<RSpec::Core::Example>, Array<RSpec::Core::ExampleGroup>] The examples or groups to order
1171
- # @yieldreturn [Array<RSpec::Core::Example>, Array<RSpec::Core::ExampleGroup>] The re-ordered examples or groups
1296
+ # @yieldparam list [Array<RSpec::Core::Example>,
1297
+ # Array<RSpec::Core::ExampleGroup>] The examples or groups to order
1298
+ # @yieldreturn [Array<RSpec::Core::Example>,
1299
+ # Array<RSpec::Core::ExampleGroup>] The re-ordered examples or groups
1172
1300
  #
1173
1301
  # @example
1174
1302
  # RSpec.configure do |rspec|
@@ -1189,7 +1317,7 @@ module RSpec
1189
1317
  # @private
1190
1318
  delegate_to_ordering_manager :seed_used?, :ordering_registry
1191
1319
 
1192
- # Set Ruby warnings on or off
1320
+ # Set Ruby warnings on or off.
1193
1321
  def warnings=(value)
1194
1322
  $VERBOSE = !!value
1195
1323
  end
@@ -1252,7 +1380,7 @@ module RSpec
1252
1380
  # `shared_examples_for`, etc) onto `main` and `Module`, instead
1253
1381
  # requiring you to prefix these methods with `RSpec.`. It enables
1254
1382
  # expect-only syntax for rspec-mocks and rspec-expectations. It
1255
- # simply disables monkey patching on whatever pieces of rspec
1383
+ # simply disables monkey patching on whatever pieces of RSpec
1256
1384
  # the user is using.
1257
1385
  #
1258
1386
  # @note It configures rspec-mocks and rspec-expectations only
@@ -1265,7 +1393,7 @@ module RSpec
1265
1393
  #
1266
1394
  # @example
1267
1395
  #
1268
- # # It disables all monkey patching
1396
+ # # It disables all monkey patching.
1269
1397
  # RSpec.configure do |config|
1270
1398
  # config.disable_monkey_patching!
1271
1399
  # end
@@ -1295,33 +1423,142 @@ module RSpec
1295
1423
 
1296
1424
  # Defines a callback that can assign derived metadata values.
1297
1425
  #
1298
- # @param filters [Array<Symbol>, Hash] metadata filters that determine which example
1299
- # or group metadata hashes the callback will be triggered for. If none are given,
1300
- # the callback will be run against the metadata hashes of all groups and examples.
1301
- # @yieldparam metadata [Hash] original metadata hash from an example or group. Mutate this in
1302
- # your block as needed.
1426
+ # @param filters [Array<Symbol>, Hash] metadata filters that determine
1427
+ # which example or group metadata hashes the callback will be triggered
1428
+ # for. If none are given, the callback will be run against the metadata
1429
+ # hashes of all groups and examples.
1430
+ # @yieldparam metadata [Hash] original metadata hash from an example or
1431
+ # group. Mutate this in your block as needed.
1303
1432
  #
1304
1433
  # @example
1305
1434
  # RSpec.configure do |config|
1306
- # # Tag all groups and examples in the spec/unit directory with :type => :unit
1435
+ # # Tag all groups and examples in the spec/unit directory with
1436
+ # # :type => :unit
1307
1437
  # config.define_derived_metadata(:file_path => %r{/spec/unit/}) do |metadata|
1308
1438
  # metadata[:type] = :unit
1309
1439
  # end
1310
1440
  # end
1311
1441
  def define_derived_metadata(*filters, &block)
1312
1442
  meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1313
- @derived_metadata_blocks << [meta, block]
1443
+ @derived_metadata_blocks.append(block, meta)
1314
1444
  end
1315
1445
 
1316
1446
  # @private
1317
1447
  def apply_derived_metadata_to(metadata)
1318
- @derived_metadata_blocks.each do |filter, block|
1319
- block.call(metadata) if filter.empty? || MetadataFilter.any_apply?(filter, metadata)
1448
+ @derived_metadata_blocks.items_for(metadata).each do |block|
1449
+ block.call(metadata)
1320
1450
  end
1321
1451
  end
1322
1452
 
1453
+ # Defines a `before` hook. See {Hooks#before} for full docs.
1454
+ #
1455
+ # This method differs from {Hooks#before} in only one way: it supports
1456
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once before
1457
+ # the first example of the entire suite is executed.
1458
+ #
1459
+ # @see #prepend_before
1460
+ # @see #after
1461
+ # @see #append_after
1462
+ def before(*args, &block)
1463
+ handle_suite_hook(args, @before_suite_hooks, :push,
1464
+ Hooks::BeforeHook, block) || super(*args, &block)
1465
+ end
1466
+ alias_method :append_before, :before
1467
+
1468
+ # Adds `block` to the start of the list of `before` blocks in the same
1469
+ # scope (`:example`, `:context`, or `:suite`), in contrast to {#before},
1470
+ # which adds the hook to the end of the list.
1471
+ #
1472
+ # See {Hooks#before} for full `before` hook docs.
1473
+ #
1474
+ # This method differs from {Hooks#prepend_before} in only one way: it supports
1475
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once before
1476
+ # the first example of the entire suite is executed.
1477
+ #
1478
+ # @see #before
1479
+ # @see #after
1480
+ # @see #append_after
1481
+ def prepend_before(*args, &block)
1482
+ handle_suite_hook(args, @before_suite_hooks, :unshift,
1483
+ Hooks::BeforeHook, block) || super(*args, &block)
1484
+ end
1485
+
1486
+ # Defines a `after` hook. See {Hooks#after} for full docs.
1487
+ #
1488
+ # This method differs from {Hooks#after} in only one way: it supports
1489
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once after
1490
+ # the last example of the entire suite is executed.
1491
+ #
1492
+ # @see #append_after
1493
+ # @see #before
1494
+ # @see #prepend_before
1495
+ def after(*args, &block)
1496
+ handle_suite_hook(args, @after_suite_hooks, :unshift,
1497
+ Hooks::AfterHook, block) || super(*args, &block)
1498
+ end
1499
+ alias_method :prepend_after, :after
1500
+
1501
+ # Adds `block` to the end of the list of `after` blocks in the same
1502
+ # scope (`:example`, `:context`, or `:suite`), in contrast to {#after},
1503
+ # which adds the hook to the start of the list.
1504
+ #
1505
+ # See {Hooks#after} for full `after` hook docs.
1506
+ #
1507
+ # This method differs from {Hooks#append_after} in only one way: it supports
1508
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once after
1509
+ # the last example of the entire suite is executed.
1510
+ #
1511
+ # @see #append_after
1512
+ # @see #before
1513
+ # @see #prepend_before
1514
+ def append_after(*args, &block)
1515
+ handle_suite_hook(args, @after_suite_hooks, :push,
1516
+ Hooks::AfterHook, block) || super(*args, &block)
1517
+ end
1518
+
1519
+ # @private
1520
+ def with_suite_hooks
1521
+ return yield if dry_run?
1522
+
1523
+ hook_context = SuiteHookContext.new
1524
+ begin
1525
+ run_hooks_with(@before_suite_hooks, hook_context)
1526
+ yield
1527
+ ensure
1528
+ run_hooks_with(@after_suite_hooks, hook_context)
1529
+ end
1530
+ end
1531
+
1532
+ # @private
1533
+ # Holds the various registered hooks. Here we use a FilterableItemRepository
1534
+ # implementation that is specifically optimized for the read/write patterns
1535
+ # of the config object.
1536
+ def hooks
1537
+ @hooks ||= HookCollections.new(self, FilterableItemRepository::QueryOptimized)
1538
+ end
1539
+
1323
1540
  private
1324
1541
 
1542
+ def handle_suite_hook(args, collection, append_or_prepend, hook_type, block)
1543
+ scope, meta = *args
1544
+ return nil unless scope == :suite
1545
+
1546
+ if meta
1547
+ # TODO: in RSpec 4, consider raising an error here.
1548
+ # We warn only for backwards compatibility.
1549
+ RSpec.warn_with "WARNING: `:suite` hooks do not support metadata since " \
1550
+ "they apply to the suite as a whole rather than " \
1551
+ "any individual example or example group that has metadata. " \
1552
+ "The metadata you have provided (#{meta.inspect}) will be ignored."
1553
+ end
1554
+
1555
+ collection.__send__(append_or_prepend, hook_type.new(block, {}))
1556
+ end
1557
+
1558
+ def run_hooks_with(hooks, hook_context)
1559
+ hooks.each { |h| h.run(hook_context) }
1560
+ end
1561
+
1325
1562
  def get_files_to_run(paths)
1326
1563
  FlatMap.flat_map(paths_to_check(paths)) do |path|
1327
1564
  path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
@@ -1331,7 +1568,7 @@ module RSpec
1331
1568
 
1332
1569
  def paths_to_check(paths)
1333
1570
  return paths if pattern_might_load_specs_from_vendored_dirs?
1334
- paths + ['.']
1571
+ paths + [Dir.getwd]
1335
1572
  end
1336
1573
 
1337
1574
  def pattern_might_load_specs_from_vendored_dirs?
@@ -1386,8 +1623,8 @@ module RSpec
1386
1623
  $0.split(File::SEPARATOR).last
1387
1624
  end
1388
1625
 
1389
- def value_for(key, default=nil)
1390
- @preferred_options.key?(key) ? @preferred_options[key] : default
1626
+ def value_for(key)
1627
+ @preferred_options.fetch(key) { yield }
1391
1628
  end
1392
1629
 
1393
1630
  def assert_no_example_groups_defined(config_option)
@@ -1428,7 +1665,8 @@ module RSpec
1428
1665
 
1429
1666
  def update_pattern_attr(name, value)
1430
1667
  if @spec_files_loaded
1431
- RSpec.warning "Configuring `#{name}` to #{value} has no effect since RSpec has already loaded the spec files."
1668
+ RSpec.warning "Configuring `#{name}` to #{value} has no effect since " \
1669
+ "RSpec has already loaded the spec files."
1432
1670
  end
1433
1671
 
1434
1672
  instance_variable_set(:"@#{name}", value)