rspec-core 3.0.4 → 3.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +2 -1
  5. data/Changelog.md +888 -2
  6. data/{License.txt → LICENSE.md} +6 -5
  7. data/README.md +165 -24
  8. data/lib/rspec/autorun.rb +1 -0
  9. data/lib/rspec/core/backtrace_formatter.rb +19 -20
  10. data/lib/rspec/core/bisect/coordinator.rb +62 -0
  11. data/lib/rspec/core/bisect/example_minimizer.rb +173 -0
  12. data/lib/rspec/core/bisect/fork_runner.rb +138 -0
  13. data/lib/rspec/core/bisect/server.rb +61 -0
  14. data/lib/rspec/core/bisect/shell_command.rb +126 -0
  15. data/lib/rspec/core/bisect/shell_runner.rb +73 -0
  16. data/lib/rspec/core/bisect/utilities.rb +69 -0
  17. data/lib/rspec/core/configuration.rb +1287 -246
  18. data/lib/rspec/core/configuration_options.rb +95 -35
  19. data/lib/rspec/core/did_you_mean.rb +46 -0
  20. data/lib/rspec/core/drb.rb +21 -12
  21. data/lib/rspec/core/dsl.rb +10 -6
  22. data/lib/rspec/core/example.rb +305 -113
  23. data/lib/rspec/core/example_group.rb +431 -223
  24. data/lib/rspec/core/example_status_persister.rb +235 -0
  25. data/lib/rspec/core/filter_manager.rb +86 -115
  26. data/lib/rspec/core/flat_map.rb +6 -4
  27. data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
  28. data/lib/rspec/core/formatters/base_formatter.rb +14 -116
  29. data/lib/rspec/core/formatters/base_text_formatter.rb +18 -21
  30. data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
  31. data/lib/rspec/core/formatters/bisect_progress_formatter.rb +157 -0
  32. data/lib/rspec/core/formatters/console_codes.rb +29 -18
  33. data/lib/rspec/core/formatters/deprecation_formatter.rb +16 -16
  34. data/lib/rspec/core/formatters/documentation_formatter.rb +49 -16
  35. data/lib/rspec/core/formatters/exception_presenter.rb +525 -0
  36. data/lib/rspec/core/formatters/failure_list_formatter.rb +23 -0
  37. data/lib/rspec/core/formatters/fallback_message_formatter.rb +28 -0
  38. data/lib/rspec/core/formatters/helpers.rb +45 -15
  39. data/lib/rspec/core/formatters/html_formatter.rb +33 -28
  40. data/lib/rspec/core/formatters/html_printer.rb +30 -20
  41. data/lib/rspec/core/formatters/html_snippet_extractor.rb +120 -0
  42. data/lib/rspec/core/formatters/json_formatter.rb +18 -9
  43. data/lib/rspec/core/formatters/profile_formatter.rb +10 -9
  44. data/lib/rspec/core/formatters/progress_formatter.rb +5 -4
  45. data/lib/rspec/core/formatters/protocol.rb +182 -0
  46. data/lib/rspec/core/formatters/snippet_extractor.rb +113 -82
  47. data/lib/rspec/core/formatters/syntax_highlighter.rb +91 -0
  48. data/lib/rspec/core/formatters.rb +81 -41
  49. data/lib/rspec/core/hooks.rb +314 -244
  50. data/lib/rspec/core/invocations.rb +87 -0
  51. data/lib/rspec/core/memoized_helpers.rb +161 -51
  52. data/lib/rspec/core/metadata.rb +132 -61
  53. data/lib/rspec/core/metadata_filter.rb +224 -64
  54. data/lib/rspec/core/minitest_assertions_adapter.rb +6 -3
  55. data/lib/rspec/core/mocking_adapters/flexmock.rb +4 -2
  56. data/lib/rspec/core/mocking_adapters/mocha.rb +11 -9
  57. data/lib/rspec/core/mocking_adapters/null.rb +2 -0
  58. data/lib/rspec/core/mocking_adapters/rr.rb +3 -1
  59. data/lib/rspec/core/mocking_adapters/rspec.rb +3 -1
  60. data/lib/rspec/core/notifications.rb +192 -206
  61. data/lib/rspec/core/option_parser.rb +174 -69
  62. data/lib/rspec/core/ordering.rb +48 -35
  63. data/lib/rspec/core/output_wrapper.rb +29 -0
  64. data/lib/rspec/core/pending.rb +25 -33
  65. data/lib/rspec/core/profiler.rb +34 -0
  66. data/lib/rspec/core/project_initializer/.rspec +0 -2
  67. data/lib/rspec/core/project_initializer/spec/spec_helper.rb +59 -39
  68. data/lib/rspec/core/project_initializer.rb +5 -3
  69. data/lib/rspec/core/rake_task.rb +99 -55
  70. data/lib/rspec/core/reporter.rb +128 -15
  71. data/lib/rspec/core/ruby_project.rb +14 -6
  72. data/lib/rspec/core/runner.rb +96 -45
  73. data/lib/rspec/core/sandbox.rb +37 -0
  74. data/lib/rspec/core/set.rb +54 -0
  75. data/lib/rspec/core/shared_example_group.rb +133 -43
  76. data/lib/rspec/core/shell_escape.rb +49 -0
  77. data/lib/rspec/core/test_unit_assertions_adapter.rb +4 -4
  78. data/lib/rspec/core/version.rb +1 -1
  79. data/lib/rspec/core/warnings.rb +6 -6
  80. data/lib/rspec/core/world.rb +172 -68
  81. data/lib/rspec/core.rb +66 -21
  82. data.tar.gz.sig +0 -0
  83. metadata +93 -69
  84. metadata.gz.sig +0 -0
  85. data/lib/rspec/core/backport_random.rb +0 -336
@@ -1,17 +1,32 @@
1
- require 'fileutils'
2
-
3
1
  RSpec::Support.require_rspec_core "backtrace_formatter"
4
2
  RSpec::Support.require_rspec_core "ruby_project"
5
3
  RSpec::Support.require_rspec_core "formatters/deprecation_formatter"
4
+ RSpec::Support.require_rspec_core "output_wrapper"
6
5
 
7
6
  module RSpec
8
7
  module Core
8
+ # rubocop:disable Metrics/ClassLength
9
+
9
10
  # Stores runtime configuration information.
10
11
  #
11
- # Configuration options are loaded from `~/.rspec`, `.rspec`,
12
- # `.rspec-local`, command line switches, and the `SPEC_OPTS` environment
13
- # variable (listed in lowest to highest precedence; for example, an option
14
- # in `~/.rspec` can be overridden by an option in `.rspec-local`).
12
+ # Configuration options are loaded from multiple files and joined together
13
+ # with command-line switches and the `SPEC_OPTS` environment variable.
14
+ #
15
+ # Precedence order (where later entries overwrite earlier entries on
16
+ # conflicts):
17
+ #
18
+ # * Global (`$XDG_CONFIG_HOME/rspec/options`, or `~/.rspec` if it does
19
+ # not exist)
20
+ # * Project-specific (`./.rspec`)
21
+ # * Local (`./.rspec-local`)
22
+ # * Command-line options
23
+ # * `SPEC_OPTS`
24
+ #
25
+ # For example, an option set in the local file will override an option set
26
+ # in your global file.
27
+ #
28
+ # The global, project-specific and local files can all be overridden with a
29
+ # separate custom file using the --options command-line parameter.
15
30
  #
16
31
  # @example Standard settings
17
32
  # RSpec.configure do |c|
@@ -32,27 +47,37 @@ module RSpec
32
47
  class Configuration
33
48
  include RSpec::Core::Hooks
34
49
 
50
+ # Module that holds `attr_reader` declarations. It's in a separate
51
+ # module to allow us to override those methods and use `super`.
52
+ # @private
53
+ Readers = Module.new
54
+ include Readers
55
+
35
56
  # @private
36
57
  class MustBeConfiguredBeforeExampleGroupsError < StandardError; end
37
58
 
38
59
  # @private
39
60
  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)
61
+ Readers.class_eval do
62
+ remove_method name if method_defined?(name)
63
+ attr_reader name
43
64
  end
65
+
66
+ define_method(name) { value_for(name) { super() } }
44
67
  end
45
68
 
46
69
  # @private
47
- def self.define_aliases(name, alias_name)
70
+ def self.define_alias(name, alias_name)
48
71
  alias_method alias_name, name
49
72
  alias_method "#{alias_name}=", "#{name}="
50
- define_predicate_for alias_name
73
+ define_predicate alias_name
51
74
  end
52
75
 
53
76
  # @private
54
- def self.define_predicate_for(*names)
55
- names.each {|name| alias_method "#{name}?", name}
77
+ def self.define_predicate(name)
78
+ define_method "#{name}?" do
79
+ !!send(name)
80
+ end
56
81
  end
57
82
 
58
83
  # @private
@@ -60,27 +85,26 @@ module RSpec
60
85
  # Invoked by the `add_setting` instance method. Use that method on a
61
86
  # `Configuration` instance rather than this class method.
62
87
  def self.add_setting(name, opts={})
63
- raise "Use the instance add_setting method if you want to set a default" if opts.has_key?(:default)
88
+ raise "Use the instance add_setting method if you want to set a default" if opts.key?(:default)
64
89
  attr_writer name
65
90
  add_read_only_setting name
66
91
 
67
92
  Array(opts[:alias_with]).each do |alias_name|
68
- define_aliases(name, alias_name)
93
+ define_alias(name, alias_name)
69
94
  end
70
95
  end
71
96
 
72
97
  # @private
73
98
  #
74
- # As `add_setting` but only add the reader
99
+ # As `add_setting` but only add the reader.
75
100
  def self.add_read_only_setting(name, opts={})
76
- raise "Use the instance add_setting method if you want to set a default" if opts.has_key?(:default)
101
+ raise "Use the instance add_setting method if you want to set a default" if opts.key?(:default)
77
102
  define_reader name
78
- define_predicate_for name
103
+ define_predicate name
79
104
  end
80
105
 
81
106
  # @macro [attach] add_setting
82
107
  # @!attribute [rw] $1
83
- # @!method $1=(value)
84
108
  #
85
109
  # @macro [attach] define_reader
86
110
  # @!attribute [r] $1
@@ -89,11 +113,20 @@ module RSpec
89
113
  # Path to use if no path is provided to the `rspec` command (default:
90
114
  # `"spec"`). Allows you to just type `rspec` instead of `rspec spec` to
91
115
  # run all the examples in the `spec` directory.
92
- add_setting :default_path
116
+ #
117
+ # @note Other scripts invoking `rspec` indirectly will ignore this
118
+ # setting.
119
+ # @return [String]
120
+ add_read_only_setting :default_path
121
+ def default_path=(path)
122
+ project_source_dirs << path
123
+ @default_path = path
124
+ end
93
125
 
94
126
  # @macro add_setting
95
127
  # Run examples over DRb (default: `false`). RSpec doesn't supply the DRb
96
128
  # server, but you can use tools like spork.
129
+ # @return [Boolean]
97
130
  add_setting :drb
98
131
 
99
132
  # @macro add_setting
@@ -106,6 +139,7 @@ module RSpec
106
139
 
107
140
  # Indicates if the DSL has been exposed off of modules and `main`.
108
141
  # Default: true
142
+ # @return [Boolean]
109
143
  def expose_dsl_globally?
110
144
  Core::DSL.exposed_globally?
111
145
  end
@@ -126,26 +160,77 @@ module RSpec
126
160
 
127
161
  # Determines where deprecation warnings are printed.
128
162
  # Defaults to `$stderr`.
129
- # @return [IO, String] IO to write to or filename to write to
163
+ # @return [IO, String] IO or filename to write to
130
164
  define_reader :deprecation_stream
131
165
 
132
166
  # Determines where deprecation warnings are printed.
133
167
  # @param value [IO, String] IO to write to or filename to write to
134
168
  def deprecation_stream=(value)
135
169
  if @reporter && !value.equal?(@deprecation_stream)
136
- warn "RSpec's reporter has already been initialized with " +
137
- "#{deprecation_stream.inspect} as the deprecation stream, so your change to "+
138
- "`deprecation_stream` will be ignored. You should configure it earlier for " +
139
- "it to take effect, or use the `--deprecation-out` CLI option. " +
170
+ warn "RSpec's reporter has already been initialized with " \
171
+ "#{deprecation_stream.inspect} as the deprecation stream, so your change to "\
172
+ "`deprecation_stream` will be ignored. You should configure it earlier for " \
173
+ "it to take effect, or use the `--deprecation-out` CLI option. " \
140
174
  "(Called from #{CallerFilter.first_non_rspec_line})"
141
175
  else
142
176
  @deprecation_stream = value
143
177
  end
144
178
  end
145
179
 
146
- # @macro add_setting
147
- # Clean up and exit after the first failure (default: `false`).
148
- add_setting :fail_fast
180
+ # @macro define_reader
181
+ # The file path to use for persisting example statuses. Necessary for the
182
+ # `--only-failures` and `--next-failure` CLI options.
183
+ #
184
+ # @overload example_status_persistence_file_path
185
+ # @return [String] the file path
186
+ # @overload example_status_persistence_file_path=(value)
187
+ # @param value [String] the file path
188
+ define_reader :example_status_persistence_file_path
189
+
190
+ # Sets the file path to use for persisting example statuses. Necessary for the
191
+ # `--only-failures` and `--next-failure` CLI options.
192
+ def example_status_persistence_file_path=(value)
193
+ @example_status_persistence_file_path = value
194
+ clear_values_derived_from_example_status_persistence_file_path
195
+ end
196
+
197
+ # @macro define_reader
198
+ # Indicates if the `--only-failures` (or `--next-failure`) flag is being used.
199
+ define_reader :only_failures
200
+ alias_method :only_failures?, :only_failures
201
+
202
+ # @private
203
+ def only_failures_but_not_configured?
204
+ only_failures? && !example_status_persistence_file_path
205
+ end
206
+
207
+ # @macro define_reader
208
+ # If specified, indicates the number of failures required before cleaning
209
+ # up and exit (default: `nil`). Can also be `true` to fail and exit on first
210
+ # failure
211
+ define_reader :fail_fast
212
+
213
+ # @see fail_fast
214
+ def fail_fast=(value)
215
+ case value
216
+ when true, 'true'
217
+ @fail_fast = true
218
+ when false, 'false', 0
219
+ @fail_fast = false
220
+ when nil
221
+ @fail_fast = nil
222
+ else
223
+ @fail_fast = value.to_i
224
+
225
+ if value.to_i == 0
226
+ # TODO: in RSpec 4, consider raising an error here.
227
+ RSpec.warning "Cannot set `RSpec.configuration.fail_fast`" \
228
+ " to `#{value.inspect}`. Only `true`, `false`, `nil` and integers" \
229
+ " are valid values."
230
+ @fail_fast = true
231
+ end
232
+ end
233
+ end
149
234
 
150
235
  # @macro add_setting
151
236
  # Prints the formatter output of your suite without running any
@@ -154,143 +239,310 @@ module RSpec
154
239
 
155
240
  # @macro add_setting
156
241
  # The exit code to return if there are any failures (default: 1).
242
+ # @return [Integer]
157
243
  add_setting :failure_exit_code
158
244
 
245
+ # @macro add_setting
246
+ # The exit code to return if there are any errors outside examples (default: failure_exit_code)
247
+ # @return [Integer]
248
+ add_setting :error_exit_code
249
+
250
+ # @macro add_setting
251
+ # Whether or not to fail when there are no RSpec examples (default: false).
252
+ # @return [Boolean]
253
+ add_setting :fail_if_no_examples
254
+
159
255
  # @macro define_reader
160
- # Indicates files configured to be required
256
+ # Indicates files configured to be required.
257
+ # @return [Array<String>]
161
258
  define_reader :requires
162
259
 
163
260
  # @macro define_reader
164
- # Returns dirs that have been prepended to the load path by the `-I` command line option
261
+ # Returns dirs that have been prepended to the load path by the `-I`
262
+ # command line option.
263
+ # @return [Array<String>]
165
264
  define_reader :libs
166
265
 
167
266
  # @macro add_setting
168
267
  # Determines where RSpec will send its output.
169
268
  # Default: `$stdout`.
269
+ # @return [IO, String]
170
270
  define_reader :output_stream
171
271
 
172
- # Set the output stream for reporter
173
- # @attr value [IO] value for output, defaults to $stdout
272
+ # Set the output stream for reporter.
273
+ # @attr value [IO, String] IO to write to or filename to write to, defaults to $stdout
174
274
  def output_stream=(value)
175
275
  if @reporter && !value.equal?(@output_stream)
176
- warn "RSpec's reporter has already been initialized with " +
177
- "#{output_stream.inspect} as the output stream, so your change to "+
178
- "`output_stream` will be ignored. You should configure it earlier for " +
276
+ warn "RSpec's reporter has already been initialized with " \
277
+ "#{output_stream.inspect} as the output stream, so your change to "\
278
+ "`output_stream` will be ignored. You should configure it earlier for " \
179
279
  "it to take effect. (Called from #{CallerFilter.first_non_rspec_line})"
180
280
  else
181
281
  @output_stream = value
282
+ output_wrapper.output = @output_stream
182
283
  end
183
284
  end
184
285
 
185
286
  # @macro define_reader
186
- # Load files matching this pattern (default: `'**/*_spec.rb'`)
287
+ # Load files matching this pattern (default: `'**{,/*/**}/*_spec.rb'`).
288
+ # @return [String]
187
289
  define_reader :pattern
188
290
 
189
- # Set pattern to match files to load
291
+ # Set pattern to match files to load.
190
292
  # @attr value [String] the filename pattern to filter spec files by
191
293
  def pattern=(value)
192
- if @spec_files_loaded
193
- RSpec.warning "Configuring `pattern` to #{value} has no effect since RSpec has already loaded the spec files."
194
- end
195
- @pattern = value
196
- @files_to_run = nil
294
+ update_pattern_attr :pattern, value
197
295
  end
198
296
 
297
+ # @macro define_reader
298
+ # Exclude files matching this pattern.
299
+ # @return [String]
300
+ define_reader :exclude_pattern
301
+
302
+ # Set pattern to match files to exclude.
303
+ # @attr value [String] the filename pattern to exclude spec files by
304
+ def exclude_pattern=(value)
305
+ update_pattern_attr :exclude_pattern, value
306
+ end
307
+
308
+ # @macro add_setting
309
+ # Specifies which directories contain the source code for your project.
310
+ # When a failure occurs, RSpec looks through the backtrace to find a
311
+ # a line of source to print. It first looks for a line coming from
312
+ # one of the project source directories so that, for example, it prints
313
+ # the expectation or assertion call rather than the source code from
314
+ # the expectation or assertion framework.
315
+ # @return [Array<String>]
316
+ add_setting :project_source_dirs
317
+
199
318
  # @macro add_setting
200
319
  # Report the times for the slowest examples (default: `false`).
201
320
  # Use this to specify the number of examples to include in the profile.
202
- add_setting :profile_examples
321
+ # @return [Boolean]
322
+ attr_writer :profile_examples
323
+ define_predicate :profile_examples
203
324
 
204
325
  # @macro add_setting
205
- # Run all examples if none match the configured filters (default: `false`).
326
+ # Run all examples if none match the configured filters
327
+ # (default: `false`).
328
+ # @deprecated Use {#filter_run_when_matching} instead for the specific
329
+ # filters that you want to be ignored if none match.
206
330
  add_setting :run_all_when_everything_filtered
207
331
 
208
332
  # @macro add_setting
209
- # Color to use to indicate success.
210
- # @param color [Symbol] defaults to `:green` but can be set to one of the
211
- # following: `[:black, :white, :red, :green, :yellow,
212
- # :blue, :magenta, :cyan]`
333
+ # Color to use to indicate success. Defaults to `:green` but can be set
334
+ # to one of the following: `[:black, :white, :red, :green, :yellow,
335
+ # :blue, :magenta, :cyan]`
336
+ # @return [Symbol]
213
337
  add_setting :success_color
214
338
 
215
339
  # @macro add_setting
216
- # Color to use to print pending examples.
217
- # @param color [Symbol] defaults to `:yellow` but can be set to one of the
218
- # following: `[:black, :white, :red, :green, :yellow,
219
- # :blue, :magenta, :cyan]`
340
+ # Color to use to print pending examples. Defaults to `:yellow` but can
341
+ # be set to one of the following: `[:black, :white, :red, :green,
342
+ # :yellow, :blue, :magenta, :cyan]`
343
+ # @return [Symbol]
220
344
  add_setting :pending_color
221
345
 
222
346
  # @macro add_setting
223
- # Color to use to indicate failure.
224
- # @param color [Symbol] defaults to `:red` but can be set to one of the
225
- # following: `[:black, :white, :red, :green, :yellow,
226
- # :blue, :magenta, :cyan]`
347
+ # Color to use to indicate failure. Defaults to `:red` but can be set to
348
+ # one of the following: `[:black, :white, :red, :green, :yellow, :blue,
349
+ # :magenta, :cyan]`
350
+ # @return [Symbol]
227
351
  add_setting :failure_color
228
352
 
229
353
  # @macro add_setting
230
- # The default output color.
231
- # @param color [Symbol] defaults to `:white` but can be set to one of the
232
- # following:`[:black, :white, :red, :green, :yellow,
233
- # :blue, :magenta, :cyan]`
354
+ # The default output color. Defaults to `:white` but can be set to one of
355
+ # the following: `[:black, :white, :red, :green, :yellow, :blue,
356
+ # :magenta, :cyan]`
357
+ # @return [Symbol]
234
358
  add_setting :default_color
235
359
 
236
360
  # @macro add_setting
237
- # Color used when a pending example is fixed.
238
- # @param color [Symbol] defaults to `:blue` but can be set to one of the
239
- # following: `[:black, :white, :red, :green, :yellow,
240
- # :blue, :magenta, :cyan]`
361
+ # Color used when a pending example is fixed. Defaults to `:blue` but can
362
+ # be set to one of the following: `[:black, :white, :red, :green,
363
+ # :yellow, :blue, :magenta, :cyan]`
364
+ # @return [Symbol]
241
365
  add_setting :fixed_color
242
366
 
243
367
  # @macro add_setting
244
- # Color used to print details.
245
- # @param color [Symbol] defaults to `:cyan` but can be set to one of the
246
- # following: `[:black, :white, :red, :green, :yellow,
247
- # :blue, :magenta, :cyan]`
368
+ # Color used to print details. Defaults to `:cyan` but can be set to one
369
+ # of the following: `[:black, :white, :red, :green, :yellow, :blue,
370
+ # :magenta, :cyan]`
371
+ # @return [Symbol]
248
372
  add_setting :detail_color
249
373
 
250
- # Deprecated. This config option was added in RSpec 2 to pave the way
251
- # for this being the default behavior in RSpec 3. Now this option is
252
- # a no-op.
253
- def treat_symbols_as_metadata_keys_with_true_values=(value)
254
- RSpec.deprecate("RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=",
255
- :message => "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values= " +
256
- "is deprecated, it is now set to true as default and setting it to false has no effect.")
374
+ # @macro add_setting
375
+ # Don't print filter info i.e. "Run options: include {:focus=>true}"
376
+ # (default `false`).
377
+ # return [Boolean]
378
+ add_setting :silence_filter_announcements
379
+
380
+ # @deprecated This config option was added in RSpec 2 to pave the way
381
+ # for this being the default behavior in RSpec 3. Now this option is
382
+ # a no-op.
383
+ def treat_symbols_as_metadata_keys_with_true_values=(_value)
384
+ RSpec.deprecate(
385
+ "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=",
386
+ :message => "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values= " \
387
+ "is deprecated, it is now set to true as default and " \
388
+ "setting it to false has no effect."
389
+ )
390
+ end
391
+
392
+ # @macro define_reader
393
+ # Configures how RSpec treats metadata passed as part of a shared example
394
+ # group definition. For example, given this shared example group definition:
395
+ #
396
+ # RSpec.shared_context "uses DB", :db => true do
397
+ # around(:example) do |ex|
398
+ # MyORM.transaction(:rollback => true, &ex)
399
+ # end
400
+ # end
401
+ #
402
+ # ...there are two ways RSpec can treat the `:db => true` metadata, each
403
+ # of which has a corresponding config option:
404
+ #
405
+ # 1. `:trigger_inclusion`: this shared context will be implicitly included
406
+ # in any groups (or examples) that have `:db => true` metadata.
407
+ # 2. `:apply_to_host_groups`: the metadata will be inherited by the metadata
408
+ # hash of all host groups and examples.
409
+ #
410
+ # `:trigger_inclusion` is the legacy behavior from before RSpec 3.5 but should
411
+ # be considered deprecated. Instead, you can explicitly include a group with
412
+ # `include_context`:
413
+ #
414
+ # RSpec.describe "My model" do
415
+ # include_context "uses DB"
416
+ # end
417
+ #
418
+ # ...or you can configure RSpec to include the context based on matching metadata
419
+ # using an API that mirrors configured module inclusion:
420
+ #
421
+ # RSpec.configure do |rspec|
422
+ # rspec.include_context "uses DB", :db => true
423
+ # end
424
+ #
425
+ # `:apply_to_host_groups` is a new feature of RSpec 3.5 and will be the only
426
+ # supported behavior in RSpec 4.
427
+ #
428
+ # @overload shared_context_metadata_behavior
429
+ # @return [:trigger_inclusion, :apply_to_host_groups] the configured behavior
430
+ # @overload shared_context_metadata_behavior=(value)
431
+ # @param value [:trigger_inclusion, :apply_to_host_groups] sets the configured behavior
432
+ define_reader :shared_context_metadata_behavior
433
+ # @see shared_context_metadata_behavior
434
+ def shared_context_metadata_behavior=(value)
435
+ case value
436
+ when :trigger_inclusion, :apply_to_host_groups
437
+ @shared_context_metadata_behavior = value
438
+ else
439
+ raise ArgumentError, "Cannot set `RSpec.configuration." \
440
+ "shared_context_metadata_behavior` to `#{value.inspect}`. Only " \
441
+ "`:trigger_inclusion` and `:apply_to_host_groups` are valid values."
442
+ end
257
443
  end
258
444
 
259
- # Record the start time of the spec suite to measure load time
445
+ # Record the start time of the spec suite to measure load time.
446
+ # return [Time]
260
447
  add_setting :start_time
261
448
 
449
+ # @macro add_setting
450
+ # Use threadsafe options where available.
451
+ # Currently this will place a mutex around memoized values such as let blocks.
452
+ # return [Boolean]
453
+ add_setting :threadsafe
454
+
455
+ # @macro add_setting
456
+ # Maximum count of failed source lines to display in the failure reports.
457
+ # (default `10`).
458
+ # return [Integer]
459
+ add_setting :max_displayed_failure_line_count
460
+
461
+ # Determines which bisect runner implementation gets used to run subsets
462
+ # of the suite during a bisection. Your choices are:
463
+ #
464
+ # - `:shell`: Performs a spec run by shelling out, booting RSpec and your
465
+ # application environment each time. This runner is the most widely
466
+ # compatible runner, but is not as fast. On platforms that do not
467
+ # support forking, this is the default.
468
+ # - `:fork`: Pre-boots RSpec and your application environment in a parent
469
+ # process, and then forks a child process for each spec run. This runner
470
+ # tends to be significantly faster than the `:shell` runner but cannot
471
+ # be used in some situations. On platforms that support forking, this
472
+ # is the default. If you use this runner, you should ensure that all
473
+ # of your one-time setup logic goes in a `before(:suite)` hook instead
474
+ # of getting run at the top-level of a file loaded by `--require`.
475
+ #
476
+ # @note This option will only be used by `--bisect` if you set it in a file
477
+ # loaded via `--require`.
478
+ #
479
+ # @return [Symbol]
480
+ attr_reader :bisect_runner
481
+ def bisect_runner=(value)
482
+ if @bisect_runner_class && value != @bisect_runner
483
+ raise "`config.bisect_runner = #{value.inspect}` can no longer take " \
484
+ "effect as the #{@bisect_runner.inspect} bisect runnner is already " \
485
+ "in use. This config setting must be set in a file loaded by a " \
486
+ "`--require` option (passed at the CLI or in a `.rspec` file) for " \
487
+ "it to have any effect."
488
+ end
489
+
490
+ @bisect_runner = value
491
+ end
492
+
262
493
  # @private
494
+ # @deprecated Use {#color_mode} = :on, instead of {#color} with {#tty}
263
495
  add_setting :tty
264
496
  # @private
265
- add_setting :include_or_extend_modules
266
- # @private
267
497
  attr_writer :files_to_run
268
498
  # @private
269
- add_setting :expecting_with_rspec
499
+ attr_accessor :filter_manager, :world
270
500
  # @private
271
- attr_accessor :filter_manager
501
+ attr_accessor :static_config_filter_manager
272
502
  # @private
273
- attr_reader :backtrace_formatter, :ordering_manager
503
+ attr_reader :backtrace_formatter, :ordering_manager, :loaded_spec_files
504
+
505
+ # rubocop:disable Metrics/AbcSize
506
+ # rubocop:disable Metrics/MethodLength
274
507
 
508
+ # Build an object to store runtime configuration options and set defaults
275
509
  def initialize
510
+ # rubocop:disable Style/GlobalVars
276
511
  @start_time = $_rspec_core_load_started_at || ::RSpec::Core::Time.now
512
+ # rubocop:enable Style/GlobalVars
277
513
  @expectation_frameworks = []
278
- @include_or_extend_modules = []
514
+ @include_modules = FilterableItemRepository::QueryOptimized.new(:any?)
515
+ @extend_modules = FilterableItemRepository::QueryOptimized.new(:any?)
516
+ @prepend_modules = FilterableItemRepository::QueryOptimized.new(:any?)
517
+
518
+ @bisect_runner = RSpec::Support::RubyFeatures.fork_supported? ? :fork : :shell
519
+ @bisect_runner_class = nil
520
+
521
+ @before_suite_hooks = []
522
+ @after_suite_hooks = []
523
+
279
524
  @mock_framework = nil
280
525
  @files_or_directories_to_run = []
526
+ @loaded_spec_files = Set.new
281
527
  @color = false
282
- @pattern = '**/*_spec.rb'
528
+ @color_mode = :automatic
529
+ @pattern = '**{,/*/**}/*_spec.rb'
530
+ @exclude_pattern = ''
283
531
  @failure_exit_code = 1
532
+ @error_exit_code = nil # so it can be overridden by failure exit code
533
+ @fail_if_no_examples = false
284
534
  @spec_files_loaded = false
285
535
 
286
536
  @backtrace_formatter = BacktraceFormatter.new
287
537
 
288
538
  @default_path = 'spec'
539
+ @project_source_dirs = %w[ spec lib app ]
289
540
  @deprecation_stream = $stderr
290
541
  @output_stream = $stdout
291
542
  @reporter = nil
292
543
  @reporter_buffer = nil
293
544
  @filter_manager = FilterManager.new
545
+ @static_config_filter_manager = FilterManager.new
294
546
  @ordering_manager = Ordering::ConfigurationManager.new
295
547
  @preferred_options = {}
296
548
  @failure_color = :red
@@ -302,8 +554,16 @@ module RSpec
302
554
  @profile_examples = false
303
555
  @requires = []
304
556
  @libs = []
305
- @derived_metadata_blocks = []
557
+ @derived_metadata_blocks = FilterableItemRepository::QueryOptimized.new(:any?)
558
+ @threadsafe = true
559
+ @max_displayed_failure_line_count = 10
560
+ @world = World::Null
561
+ @shared_context_metadata_behavior = :trigger_inclusion
562
+
563
+ define_built_in_hooks
306
564
  end
565
+ # rubocop:enable Metrics/AbcSize
566
+ # rubocop:enable Metrics/MethodLength
307
567
 
308
568
  # @private
309
569
  #
@@ -311,27 +571,47 @@ module RSpec
311
571
  def force(hash)
312
572
  ordering_manager.force(hash)
313
573
  @preferred_options.merge!(hash)
574
+
575
+ return unless hash.key?(:example_status_persistence_file_path)
576
+ clear_values_derived_from_example_status_persistence_file_path
314
577
  end
315
578
 
316
579
  # @private
317
580
  def reset
318
581
  @spec_files_loaded = false
582
+ reset_reporter
583
+ end
584
+
585
+ # @private
586
+ def reset_reporter
319
587
  @reporter = nil
320
588
  @formatter_loader = nil
589
+ @output_wrapper = nil
590
+ end
591
+
592
+ # @private
593
+ def reset_filters
594
+ self.filter_manager = FilterManager.new
595
+ filter_manager.include_only(
596
+ Metadata.deep_hash_dup(static_config_filter_manager.inclusions.rules)
597
+ )
598
+ filter_manager.exclude_only(
599
+ Metadata.deep_hash_dup(static_config_filter_manager.exclusions.rules)
600
+ )
321
601
  end
322
602
 
323
603
  # @overload add_setting(name)
324
604
  # @overload add_setting(name, opts)
325
605
  # @option opts [Symbol] :default
326
606
  #
327
- # set a default value for the generated getter and predicate methods:
607
+ # Set a default value for the generated getter and predicate methods:
328
608
  #
329
609
  # add_setting(:foo, :default => "default value")
330
610
  #
331
611
  # @option opts [Symbol] :alias_with
332
612
  #
333
- # Use `:alias_with` to alias the setter, getter, and predicate to another
334
- # name, or names:
613
+ # Use `:alias_with` to alias the setter, getter, and predicate to
614
+ # another name, or names:
335
615
  #
336
616
  # add_setting(:foo, :alias_with => :bar)
337
617
  # add_setting(:foo, :alias_with => [:bar, :baz])
@@ -354,7 +634,7 @@ module RSpec
354
634
  #
355
635
  # RSpec.configuration.foo=(value)
356
636
  # RSpec.configuration.foo
357
- # RSpec.configuration.foo? # returns true if foo returns anything but nil or false
637
+ # RSpec.configuration.foo? # Returns true if foo returns anything but nil or false.
358
638
  def add_setting(name, opts={})
359
639
  default = opts.delete(:default)
360
640
  (class << self; self; end).class_exec do
@@ -363,13 +643,20 @@ module RSpec
363
643
  __send__("#{name}=", default) if default
364
644
  end
365
645
 
366
- # Returns the configured mock framework adapter module
646
+ # Returns the configured mock framework adapter module.
647
+ # @return [Symbol]
367
648
  def mock_framework
368
- mock_with :rspec unless @mock_framework
649
+ if @mock_framework.nil?
650
+ begin
651
+ mock_with :rspec
652
+ rescue LoadError
653
+ mock_with :nothing
654
+ end
655
+ end
369
656
  @mock_framework
370
657
  end
371
658
 
372
- # Delegates to mock_framework=(framework)
659
+ # Delegates to mock_framework=(framework).
373
660
  def mock_framework=(framework)
374
661
  mock_with framework
375
662
  end
@@ -377,20 +664,21 @@ module RSpec
377
664
  # Regexps used to exclude lines from backtraces.
378
665
  #
379
666
  # Excludes lines from ruby (and jruby) source, installed gems, anything
380
- # in any "bin" directory, and any of the rspec libs (outside gem
667
+ # in any "bin" directory, and any of the RSpec libs (outside gem
381
668
  # installs) by default.
382
669
  #
383
670
  # You can modify the list via the getter, or replace it with the setter.
384
671
  #
385
672
  # To override this behaviour and display a full backtrace, use
386
- # `--backtrace`on the command line, in a `.rspec` file, or in the
673
+ # `--backtrace` on the command line, in a `.rspec` file, or in the
387
674
  # `rspec_options` attribute of RSpec's rake task.
675
+ # @return [Array<Regexp>]
388
676
  def backtrace_exclusion_patterns
389
677
  @backtrace_formatter.exclusion_patterns
390
678
  end
391
679
 
392
- # Set regular expressions used to exclude lines in backtrace
393
- # @param patterns [Regexp] set the backtrace exlusion pattern
680
+ # Set regular expressions used to exclude lines in backtrace.
681
+ # @param patterns [Array<Regexp>] set backtrace_formatter exclusion_patterns
394
682
  def backtrace_exclusion_patterns=(patterns)
395
683
  @backtrace_formatter.exclusion_patterns = patterns
396
684
  end
@@ -403,16 +691,39 @@ module RSpec
403
691
  # will be included.
404
692
  #
405
693
  # You can modify the list via the getter, or replace it with the setter.
694
+ # @return [Array<Regexp>]
406
695
  def backtrace_inclusion_patterns
407
696
  @backtrace_formatter.inclusion_patterns
408
697
  end
409
698
 
410
- # Set regular expressions used to include lines in backtrace
411
- # @attr patterns [Regexp] set backtrace_formatter inclusion_patterns
699
+ # Set regular expressions used to include lines in backtrace.
700
+ # @attr patterns [Array<Regexp>] set backtrace_formatter inclusion_patterns
412
701
  def backtrace_inclusion_patterns=(patterns)
413
702
  @backtrace_formatter.inclusion_patterns = patterns
414
703
  end
415
704
 
705
+ # Adds {#backtrace_exclusion_patterns} that will filter lines from
706
+ # the named gems from backtraces.
707
+ #
708
+ # @param gem_names [Array<String>] Names of the gems to filter
709
+ #
710
+ # @example
711
+ # RSpec.configure do |config|
712
+ # config.filter_gems_from_backtrace "rack", "rake"
713
+ # end
714
+ #
715
+ # @note The patterns this adds will match the named gems in their common
716
+ # locations (e.g. system gems, vendored with bundler, installed as a
717
+ # :git dependency with bundler, etc) but is not guaranteed to work for
718
+ # all possible gem locations. For example, if you have the gem source
719
+ # in a directory with a completely unrelated name, and use bundler's
720
+ # :path option, this will not filter it.
721
+ def filter_gems_from_backtrace(*gem_names)
722
+ gem_names.each do |name|
723
+ @backtrace_formatter.filter_gem(name)
724
+ end
725
+ end
726
+
416
727
  # @private
417
728
  MOCKING_ADAPTERS = {
418
729
  :rspec => :RSpec,
@@ -445,28 +756,29 @@ module RSpec
445
756
  # teardown_mocks_for_rspec
446
757
  # - called after verify_mocks_for_rspec (even if there are errors)
447
758
  #
448
- # If the module responds to `configuration` and `mock_with` receives a block,
449
- # it will yield the configuration object to the block e.g.
759
+ # If the module responds to `configuration` and `mock_with` receives a
760
+ # block, it will yield the configuration object to the block e.g.
450
761
  #
451
762
  # config.mock_with OtherMockFrameworkAdapter do |mod_config|
452
763
  # mod_config.custom_setting = true
453
764
  # end
454
765
  def mock_with(framework)
455
- framework_module = if framework.is_a?(Module)
456
- framework
457
- else
458
- const_name = MOCKING_ADAPTERS.fetch(framework) do
459
- raise ArgumentError,
460
- "Unknown mocking framework: #{framework.inspect}. " +
461
- "Pass a module or one of #{MOCKING_ADAPTERS.keys.inspect}"
766
+ framework_module =
767
+ if framework.is_a?(Module)
768
+ framework
769
+ else
770
+ const_name = MOCKING_ADAPTERS.fetch(framework) do
771
+ raise ArgumentError,
772
+ "Unknown mocking framework: #{framework.inspect}. " \
773
+ "Pass a module or one of #{MOCKING_ADAPTERS.keys.inspect}"
774
+ end
775
+
776
+ RSpec::Support.require_rspec_core "mocking_adapters/#{const_name.to_s.downcase}"
777
+ RSpec::Core::MockingAdapters.const_get(const_name)
462
778
  end
463
779
 
464
- RSpec::Support.require_rspec_core "mocking_adapters/#{const_name.to_s.downcase}"
465
- RSpec::Core::MockingAdapters.const_get(const_name)
466
- end
467
-
468
780
  new_name, old_name = [framework_module, @mock_framework].map do |mod|
469
- mod.respond_to?(:framework_name) ? mod.framework_name : :unnamed
781
+ mod.respond_to?(:framework_name) ? mod.framework_name : :unnamed
470
782
  end
471
783
 
472
784
  unless new_name == old_name
@@ -474,7 +786,8 @@ module RSpec
474
786
  end
475
787
 
476
788
  if block_given?
477
- raise "#{framework_module} must respond to `configuration` so that mock_with can yield it." unless framework_module.respond_to?(:configuration)
789
+ raise "#{framework_module} must respond to `configuration` so that " \
790
+ "mock_with can yield it." unless framework_module.respond_to?(:configuration)
478
791
  yield framework_module.configuration
479
792
  end
480
793
 
@@ -483,11 +796,17 @@ module RSpec
483
796
 
484
797
  # Returns the configured expectation framework adapter module(s)
485
798
  def expectation_frameworks
486
- expect_with :rspec if @expectation_frameworks.empty?
799
+ if @expectation_frameworks.empty?
800
+ begin
801
+ expect_with :rspec
802
+ rescue LoadError
803
+ expect_with Module.new
804
+ end
805
+ end
487
806
  @expectation_frameworks
488
807
  end
489
808
 
490
- # Delegates to expect_with(framework)
809
+ # Delegates to expect_with(framework).
491
810
  def expectation_framework=(framework)
492
811
  expect_with(framework)
493
812
  end
@@ -522,7 +841,13 @@ module RSpec
522
841
  framework
523
842
  when :rspec
524
843
  require 'rspec/expectations'
525
- self.expecting_with_rspec = true
844
+
845
+ # Tag this exception class so our exception formatting logic knows
846
+ # that it satisfies the `MultipleExceptionError` interface.
847
+ ::RSpec::Expectations::MultipleExpectationsNotMetError.__send__(
848
+ :include, MultipleExceptionError::InterfaceTag
849
+ )
850
+
526
851
  ::RSpec::Matchers
527
852
  when :test_unit
528
853
  require 'rspec/core/test_unit_assertions_adapter'
@@ -540,56 +865,79 @@ module RSpec
540
865
  end
541
866
 
542
867
  if block_given?
543
- 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
544
- raise "#{modules.first} must respond to `configuration` so that expect_with can yield it." unless modules.first.respond_to?(:configuration)
868
+ raise "expect_with only accepts a block with a single argument. " \
869
+ "Call expect_with #{modules.length} times, " \
870
+ "once with each argument, instead." if modules.length > 1
871
+ raise "#{modules.first} must respond to `configuration` so that " \
872
+ "expect_with can yield it." unless modules.first.respond_to?(:configuration)
545
873
  yield modules.first.configuration
546
874
  end
547
875
 
548
876
  @expectation_frameworks.push(*modules)
549
877
  end
550
878
 
551
- # Check if full backtrace is enabled
879
+ # Check if full backtrace is enabled.
552
880
  # @return [Boolean] is full backtrace enabled
553
881
  def full_backtrace?
554
882
  @backtrace_formatter.full_backtrace?
555
883
  end
556
884
 
557
- # Toggle full backtrace
885
+ # Toggle full backtrace.
558
886
  # @attr true_or_false [Boolean] toggle full backtrace display
559
887
  def full_backtrace=(true_or_false)
560
888
  @backtrace_formatter.full_backtrace = true_or_false
561
889
  end
562
890
 
563
- # Returns the configuration option for color, but should not
564
- # be used to check if color is supported.
891
+ # Enables color output if the output is a TTY. As of RSpec 3.6, this is
892
+ # the default behavior and this option is retained only for backwards
893
+ # compatibility.
565
894
  #
895
+ # @deprecated No longer recommended because of complex behavior. Instead,
896
+ # rely on the fact that TTYs will display color by default, or set
897
+ # {#color_mode} to :on to display color on a non-TTY output.
898
+ # @see color_mode
566
899
  # @see color_enabled?
567
900
  # @return [Boolean]
568
901
  def color
569
- value_for(:color, @color)
902
+ value_for(:color) { @color }
570
903
  end
571
904
 
572
- # Check if color is enabled for a particular output
573
- # @param output [IO] an output stream to use, defaults to the current
574
- # `output_stream`
905
+ # The mode for determining whether to display output in color. One of:
906
+ #
907
+ # - :automatic - the output will be in color if the output is a TTY (the
908
+ # default)
909
+ # - :on - the output will be in color, whether or not the output is a TTY
910
+ # - :off - the output will not be in color
911
+ #
912
+ # @see color_enabled?
575
913
  # @return [Boolean]
576
- def color_enabled?(output = output_stream)
577
- output_to_tty?(output) && color
914
+ def color_mode
915
+ value_for(:color_mode) { @color_mode }
578
916
  end
579
917
 
580
- # Toggle output color
581
- # @attr true_or_false [Boolean] toggle color enabled
582
- def color=(true_or_false)
583
- if true_or_false
584
- if RSpec.world.windows_os? and not ENV['ANSICON']
585
- RSpec.warning "You must use ANSICON 1.31 or later (http://adoxa.3eeweb.com/ansicon/) to use colour on Windows"
586
- @color = false
587
- else
588
- @color = true
589
- end
918
+ # Check if color is enabled for a particular output.
919
+ # @param output [IO] an output stream to use, defaults to the current
920
+ # `output_stream`
921
+ # @return [Boolean]
922
+ def color_enabled?(output=output_stream)
923
+ case color_mode
924
+ when :on then true
925
+ when :off then false
926
+ else # automatic
927
+ output_to_tty?(output) || (color && tty?)
590
928
  end
591
929
  end
592
930
 
931
+ # Set the color mode.
932
+ attr_writer :color_mode
933
+
934
+ # Toggle output color.
935
+ #
936
+ # @deprecated No longer recommended because of complex behavior. Instead,
937
+ # rely on the fact that TTYs will display color by default, or set
938
+ # {:color_mode} to :on to display color on a non-TTY output.
939
+ attr_writer :color
940
+
593
941
  # @private
594
942
  def libs=(libs)
595
943
  libs.map do |lib|
@@ -601,7 +949,7 @@ module RSpec
601
949
  # Run examples matching on `description` in all files to run.
602
950
  # @param description [String, Regexp] the pattern to filter on
603
951
  def full_description=(description)
604
- filter_run :full_description => Regexp.union(*Array(description).map {|d| Regexp.new(d) })
952
+ filter_run :full_description => Regexp.union(*Array(description).map { |d| Regexp.new(d) })
605
953
  end
606
954
 
607
955
  # @return [Array] full description filter
@@ -610,19 +958,22 @@ module RSpec
610
958
  end
611
959
 
612
960
  # @overload add_formatter(formatter)
961
+ # @overload add_formatter(formatter, output)
613
962
  #
614
- # Adds a formatter to the formatters collection. `formatter` can be a
615
- # string representing any of the built-in formatters (see
616
- # `built_in_formatter`), or a custom formatter class.
963
+ # @param formatter [Class, String, Object] formatter to use. Can be any of the
964
+ # string values supported from the CLI (`p`/`progress`,
965
+ # `d`/`doc`/`documentation`, `h`/`html`, or `j`/`json`), any
966
+ # class that implements the formatter protocol and has registered
967
+ # itself with RSpec as a formatter, or a formatter instance.
968
+ # @param output [String, IO] where the formatter will write its output.
969
+ # Can be an IO object or a string path to a file. If not provided,
970
+ # the configured `output_stream` (`$stdout`, by default) will be used.
617
971
  #
618
- # ### Note
972
+ # Adds a formatter to the set RSpec will use for this run.
619
973
  #
620
- # For internal purposes, `add_formatter` also accepts the name of a class
621
- # and paths to use for output streams, but you should consider that a
622
- # private api that may change at any time without notice.
623
- def add_formatter(formatter_to_use, *paths)
624
- paths << output_stream if paths.empty?
625
- formatter_loader.add formatter_to_use, *paths
974
+ # @see RSpec::Core::Formatters::Protocol
975
+ def add_formatter(formatter, output=output_wrapper)
976
+ formatter_loader.add(formatter, output)
626
977
  end
627
978
  alias_method :formatter=, :add_formatter
628
979
 
@@ -680,14 +1031,14 @@ module RSpec
680
1031
  end
681
1032
  end
682
1033
 
683
- # @private
1034
+ # @return [RSpec::Core::Reporter] the currently configured reporter
684
1035
  def reporter
685
1036
  # @reporter_buffer should only ever be set in this method to cover
686
1037
  # initialization of @reporter.
687
1038
  @reporter_buffer || @reporter ||=
688
1039
  begin
689
1040
  @reporter_buffer = DeprecationReporterBuffer.new
690
- formatter_loader.setup_default output_stream, deprecation_stream
1041
+ formatter_loader.prepare_default output_wrapper, deprecation_stream
691
1042
  @reporter_buffer.play_onto(formatter_loader.reporter)
692
1043
  @reporter_buffer = nil
693
1044
  formatter_loader.reporter
@@ -696,10 +1047,10 @@ module RSpec
696
1047
 
697
1048
  # @api private
698
1049
  #
699
- # Defaults `profile_examples` to 10 examples when `@profile_examples` is `true`.
700
- #
1050
+ # Defaults `profile_examples` to 10 examples when `@profile_examples` is
1051
+ # `true`.
701
1052
  def profile_examples
702
- profile = value_for(:profile_examples, @profile_examples)
1053
+ profile = value_for(:profile_examples) { @profile_examples }
703
1054
  if profile && !profile.is_a?(Integer)
704
1055
  10
705
1056
  else
@@ -710,17 +1061,66 @@ module RSpec
710
1061
  # @private
711
1062
  def files_or_directories_to_run=(*files)
712
1063
  files = files.flatten
713
- files << default_path if (command == 'rspec' || Runner.running_in_drb?) && default_path && files.empty?
1064
+
1065
+ if (command == 'rspec' || Runner.running_in_drb?) && default_path && files.empty?
1066
+ files << default_path
1067
+ end
1068
+
714
1069
  @files_or_directories_to_run = files
715
1070
  @files_to_run = nil
716
1071
  end
717
1072
 
718
- # The spec files RSpec will run
1073
+ # The spec files RSpec will run.
719
1074
  # @return [Array] specified files about to run
720
1075
  def files_to_run
721
1076
  @files_to_run ||= get_files_to_run(@files_or_directories_to_run)
722
1077
  end
723
1078
 
1079
+ # @private
1080
+ def last_run_statuses
1081
+ @last_run_statuses ||= Hash.new(UNKNOWN_STATUS).tap do |statuses|
1082
+ if (path = example_status_persistence_file_path)
1083
+ begin
1084
+ ExampleStatusPersister.load_from(path).inject(statuses) do |hash, example|
1085
+ status = example[:status]
1086
+ status = UNKNOWN_STATUS unless VALID_STATUSES.include?(status)
1087
+ hash[example.fetch(:example_id)] = status
1088
+ hash
1089
+ end
1090
+ rescue SystemCallError => e
1091
+ RSpec.warning "Could not read from #{path.inspect} (configured as " \
1092
+ "`config.example_status_persistence_file_path`) due " \
1093
+ "to a system error: #{e.inspect}. Please check that " \
1094
+ "the config option is set to an accessible, valid " \
1095
+ "file path", :call_site => nil
1096
+ end
1097
+ end
1098
+ end
1099
+ end
1100
+
1101
+ # @private
1102
+ UNKNOWN_STATUS = "unknown".freeze
1103
+
1104
+ # @private
1105
+ FAILED_STATUS = "failed".freeze
1106
+
1107
+ # @private
1108
+ PASSED_STATUS = "passed".freeze
1109
+
1110
+ # @private
1111
+ PENDING_STATUS = "pending".freeze
1112
+
1113
+ # @private
1114
+ VALID_STATUSES = [UNKNOWN_STATUS, FAILED_STATUS, PASSED_STATUS, PENDING_STATUS]
1115
+
1116
+ # @private
1117
+ def spec_files_with_failures
1118
+ @spec_files_with_failures ||= last_run_statuses.inject(Set.new) do |files, (id, status)|
1119
+ files << Example.parse_id(id).first if status == FAILED_STATUS
1120
+ files
1121
+ end.to_a
1122
+ end
1123
+
724
1124
  # Creates a method that delegates to `example` including the submitted
725
1125
  # `args`. Used internally to add variants of `example` like `pending`:
726
1126
  # @param name [String] example name alias
@@ -729,8 +1129,8 @@ module RSpec
729
1129
  # @note The specific example alias below (`pending`) is already
730
1130
  # defined for you.
731
1131
  # @note Use with caution. This extends the language used in your
732
- # specs, but does not add any additional documentation. We use this
733
- # in rspec to define methods like `focus` and `xit`, but we also add
1132
+ # specs, but does not add any additional documentation. We use this
1133
+ # in RSpec to define methods like `focus` and `xit`, but we also add
734
1134
  # docs for those methods.
735
1135
  #
736
1136
  # @example
@@ -740,7 +1140,7 @@ module RSpec
740
1140
  #
741
1141
  # # This lets you do this:
742
1142
  #
743
- # describe Thing do
1143
+ # RSpec.describe Thing do
744
1144
  # pending "does something" do
745
1145
  # thing = Thing.new
746
1146
  # end
@@ -748,7 +1148,7 @@ module RSpec
748
1148
  #
749
1149
  # # ... which is the equivalent of
750
1150
  #
751
- # describe Thing do
1151
+ # RSpec.describe Thing do
752
1152
  # it "does something", :pending => true do
753
1153
  # thing = Thing.new
754
1154
  # end
@@ -801,7 +1201,7 @@ module RSpec
801
1201
  #
802
1202
  # # allows the user to include a shared example group like:
803
1203
  #
804
- # describe Entity do
1204
+ # RSpec.describe Entity do
805
1205
  # it_has_behavior 'sortability' do
806
1206
  # let(:sortable) { Entity.new }
807
1207
  # end
@@ -813,10 +1213,10 @@ module RSpec
813
1213
  # # ...sortability examples here
814
1214
  #
815
1215
  # @note Use with caution. This extends the language used in your
816
- # specs, but does not add any additional documentation. We use this
817
- # in rspec to define `it_should_behave_like` (for backward
1216
+ # specs, but does not add any additional documentation. We use this
1217
+ # in RSpec to define `it_should_behave_like` (for backward
818
1218
  # compatibility), but we also add docs for that method.
819
- def alias_it_behaves_like_to(new_name, report_label = '')
1219
+ def alias_it_behaves_like_to(new_name, report_label='')
820
1220
  RSpec::Core::ExampleGroup.define_nested_shared_group_method(new_name, report_label)
821
1221
  end
822
1222
  alias_method :alias_it_should_behave_like_to, :alias_it_behaves_like_to
@@ -831,32 +1231,48 @@ module RSpec
831
1231
  # or config files (e.g. `.rspec`).
832
1232
  #
833
1233
  # @example
834
- # # given this declaration
1234
+ # # Given this declaration.
835
1235
  # describe "something", :foo => 'bar' do
836
1236
  # # ...
837
1237
  # end
838
1238
  #
839
- # # any of the following will include that group
1239
+ # # Any of the following will include that group.
840
1240
  # config.filter_run_including :foo => 'bar'
841
1241
  # config.filter_run_including :foo => /^ba/
842
1242
  # config.filter_run_including :foo => lambda {|v| v == 'bar'}
843
1243
  # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
844
1244
  #
845
- # # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
1245
+ # # Given a proc with an arity of 1, the lambda is passed the value
1246
+ # # related to the key, e.g.
846
1247
  # config.filter_run_including :foo => lambda {|v| v == 'bar'}
847
1248
  #
848
- # # given a proc with an arity of 2, the lambda is passed the value related to the key,
849
- # # and the metadata itself e.g.
1249
+ # # Given a proc with an arity of 2, the lambda is passed the value
1250
+ # # related to the key, and the metadata itself e.g.
850
1251
  # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
851
1252
  #
852
1253
  # filter_run_including :foo # same as filter_run_including :foo => true
853
1254
  def filter_run_including(*args)
854
1255
  meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
855
1256
  filter_manager.include_with_low_priority meta
1257
+ static_config_filter_manager.include_with_low_priority Metadata.deep_hash_dup(meta)
856
1258
  end
857
-
858
1259
  alias_method :filter_run, :filter_run_including
859
1260
 
1261
+ # Applies the provided filter only if any of examples match, in constrast
1262
+ # to {#filter_run}, which always applies even if no examples match, in
1263
+ # which case no examples will be run. This allows you to leave configured
1264
+ # filters in place that are intended only for temporary use. The most common
1265
+ # example is focus filtering: `config.filter_run_when_matching :focus`.
1266
+ # With that configured, you can temporarily focus an example or group
1267
+ # by tagging it with `:focus` metadata, or prefixing it with an `f`
1268
+ # (as in `fdescribe`, `fcontext` and `fit`) since those are aliases for
1269
+ # `describe`/`context`/`it` with `:focus` metadata.
1270
+ def filter_run_when_matching(*args)
1271
+ when_first_matching_example_defined(*args) do
1272
+ filter_run(*args)
1273
+ end
1274
+ end
1275
+
860
1276
  # Clears and reassigns the `inclusion_filter`. Set to `nil` if you don't
861
1277
  # want any inclusion filter at all.
862
1278
  #
@@ -889,28 +1305,30 @@ module RSpec
889
1305
  # or config files (e.g. `.rspec`).
890
1306
  #
891
1307
  # @example
892
- # # given this declaration
1308
+ # # Given this declaration.
893
1309
  # describe "something", :foo => 'bar' do
894
1310
  # # ...
895
1311
  # end
896
1312
  #
897
- # # any of the following will exclude that group
1313
+ # # Any of the following will exclude that group.
898
1314
  # config.filter_run_excluding :foo => 'bar'
899
1315
  # config.filter_run_excluding :foo => /^ba/
900
1316
  # config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
901
1317
  # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
902
1318
  #
903
- # # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
1319
+ # # Given a proc with an arity of 1, the lambda is passed the value
1320
+ # # related to the key, e.g.
904
1321
  # config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
905
1322
  #
906
- # # given a proc with an arity of 2, the lambda is passed the value related to the key,
907
- # # and the metadata itself e.g.
1323
+ # # Given a proc with an arity of 2, the lambda is passed the value
1324
+ # # related to the key, and the metadata itself e.g.
908
1325
  # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
909
1326
  #
910
1327
  # filter_run_excluding :foo # same as filter_run_excluding :foo => true
911
1328
  def filter_run_excluding(*args)
912
1329
  meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
913
1330
  filter_manager.exclude_with_low_priority meta
1331
+ static_config_filter_manager.exclude_with_low_priority Metadata.deep_hash_dup(meta)
914
1332
  end
915
1333
 
916
1334
  # Clears and reassigns the `exclusion_filter`. Set to `nil` if you don't
@@ -932,8 +1350,8 @@ module RSpec
932
1350
  end
933
1351
 
934
1352
  # Tells RSpec to include `mod` in example groups. Methods defined in
935
- # `mod` are exposed to examples (not example groups). Use `filters` to
936
- # constrain the groups in which to include the module.
1353
+ # `mod` are exposed to examples (not example groups). Use `filters` to
1354
+ # constrain the groups or examples in which to include the module.
937
1355
  #
938
1356
  # @example
939
1357
  #
@@ -943,6 +1361,12 @@ module RSpec
943
1361
  # end
944
1362
  # end
945
1363
  #
1364
+ # module PreferencesHelpers
1365
+ # def preferences(user, preferences = {})
1366
+ # # ...
1367
+ # end
1368
+ # end
1369
+ #
946
1370
  # module UserHelpers
947
1371
  # def users(username)
948
1372
  # # ...
@@ -950,26 +1374,87 @@ module RSpec
950
1374
  # end
951
1375
  #
952
1376
  # RSpec.configure do |config|
953
- # config.include(UserHelpers) # included in all modules
1377
+ # config.include(UserHelpers) # included in all groups
1378
+ #
1379
+ # # included in examples with `:preferences` metadata
1380
+ # config.include(PreferenceHelpers, :preferences)
1381
+ #
1382
+ # # included in examples with `:type => :request` metadata
954
1383
  # config.include(AuthenticationHelpers, :type => :request)
955
1384
  # end
956
1385
  #
957
- # describe "edit profile", :type => :request do
1386
+ # describe "edit profile", :preferences, :type => :request do
958
1387
  # it "can be viewed by owning user" do
959
- # login_as users(:jdoe)
1388
+ # login_as preferences(users(:jdoe), :lang => 'es')
960
1389
  # get "/profiles/jdoe"
961
1390
  # assert_select ".username", :text => 'jdoe'
962
1391
  # end
963
1392
  # end
964
1393
  #
1394
+ # @note Filtered module inclusions can also be applied to
1395
+ # individual examples that have matching metadata. Just like
1396
+ # Ruby's object model is that every object has a singleton class
1397
+ # which has only a single instance, RSpec's model is that every
1398
+ # example has a singleton example group containing just the one
1399
+ # example.
1400
+ #
1401
+ # @see #include_context
965
1402
  # @see #extend
1403
+ # @see #prepend
966
1404
  def include(mod, *filters)
967
- meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
968
- include_or_extend_modules << [:include, mod, meta]
1405
+ define_mixed_in_module(mod, filters, @include_modules, :include) do |group|
1406
+ safe_include(mod, group)
1407
+ end
1408
+ end
1409
+
1410
+ # Tells RSpec to include the named shared example group in example groups.
1411
+ # Use `filters` to constrain the groups or examples in which to include
1412
+ # the example group.
1413
+ #
1414
+ # @example
1415
+ #
1416
+ # RSpec.shared_context "example admin user" do
1417
+ # let(:admin_user) { create_user(:admin) }
1418
+ # end
1419
+ #
1420
+ # RSpec.shared_context "example guest user" do
1421
+ # let(:guest_user) { create_user(:guest) }
1422
+ # end
1423
+ #
1424
+ # RSpec.configure do |config|
1425
+ # config.include_context "example guest user", :type => :request
1426
+ # config.include_context "example admin user", :admin, :type => :request
1427
+ # end
1428
+ #
1429
+ # RSpec.describe "The admin page", :type => :request do
1430
+ # it "can be viewed by admins", :admin do
1431
+ # login_with admin_user
1432
+ # get "/admin"
1433
+ # expect(response).to be_ok
1434
+ # end
1435
+ #
1436
+ # it "cannot be viewed by guests" do
1437
+ # login_with guest_user
1438
+ # get "/admin"
1439
+ # expect(response).to be_forbidden
1440
+ # end
1441
+ # end
1442
+ #
1443
+ # @note Filtered context inclusions can also be applied to
1444
+ # individual examples that have matching metadata. Just like
1445
+ # Ruby's object model is that every object has a singleton class
1446
+ # which has only a single instance, RSpec's model is that every
1447
+ # example has a singleton example group containing just the one
1448
+ # example.
1449
+ #
1450
+ # @see #include
1451
+ def include_context(shared_group_name, *filters)
1452
+ shared_module = world.shared_example_group_registry.find([:main], shared_group_name)
1453
+ include shared_module, *filters
969
1454
  end
970
1455
 
971
- # Tells RSpec to extend example groups with `mod`. Methods defined in
972
- # `mod` are exposed to example groups (not examples). Use `filters` to
1456
+ # Tells RSpec to extend example groups with `mod`. Methods defined in
1457
+ # `mod` are exposed to example groups (not examples). Use `filters` to
973
1458
  # constrain the groups to extend.
974
1459
  #
975
1460
  # Similar to `include`, but behavior is added to example groups, which
@@ -984,12 +1469,20 @@ module RSpec
984
1469
  # end
985
1470
  # end
986
1471
  #
1472
+ # module PermissionHelpers
1473
+ # def define_permissions
1474
+ # # ...
1475
+ # end
1476
+ # end
1477
+ #
987
1478
  # RSpec.configure do |config|
988
1479
  # config.extend(UiHelpers, :type => :request)
1480
+ # config.extend(PermissionHelpers, :with_permissions, :type => :request)
989
1481
  # end
990
1482
  #
991
- # describe "edit profile", :type => :request do
1483
+ # describe "edit profile", :with_permissions, :type => :request do
992
1484
  # run_in_browser
1485
+ # define_permissions
993
1486
  #
994
1487
  # it "does stuff in the client" do
995
1488
  # # ...
@@ -997,46 +1490,100 @@ module RSpec
997
1490
  # end
998
1491
  #
999
1492
  # @see #include
1493
+ # @see #prepend
1000
1494
  def extend(mod, *filters)
1001
- meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1002
- include_or_extend_modules << [:extend, mod, meta]
1495
+ define_mixed_in_module(mod, filters, @extend_modules, :extend) do |group|
1496
+ safe_extend(mod, group)
1497
+ end
1498
+ end
1499
+
1500
+ if RSpec::Support::RubyFeatures.module_prepends_supported?
1501
+ # Tells RSpec to prepend example groups with `mod`. Methods defined in
1502
+ # `mod` are exposed to examples (not example groups). Use `filters` to
1503
+ # constrain the groups in which to prepend the module.
1504
+ #
1505
+ # Similar to `include`, but module is included before the example group's class
1506
+ # in the ancestor chain.
1507
+ #
1508
+ # @example
1509
+ #
1510
+ # module OverrideMod
1511
+ # def override_me
1512
+ # "overridden"
1513
+ # end
1514
+ # end
1515
+ #
1516
+ # RSpec.configure do |config|
1517
+ # config.prepend(OverrideMod, :method => :prepend)
1518
+ # end
1519
+ #
1520
+ # describe "overriding example's class", :method => :prepend do
1521
+ # it "finds the user" do
1522
+ # self.class.class_eval do
1523
+ # def override_me
1524
+ # end
1525
+ # end
1526
+ # override_me # => "overridden"
1527
+ # # ...
1528
+ # end
1529
+ # end
1530
+ #
1531
+ # @see #include
1532
+ # @see #extend
1533
+ def prepend(mod, *filters)
1534
+ define_mixed_in_module(mod, filters, @prepend_modules, :prepend) do |group|
1535
+ safe_prepend(mod, group)
1536
+ end
1537
+ end
1003
1538
  end
1004
1539
 
1005
1540
  # @private
1006
1541
  #
1007
- # Used internally to extend a group with modules using `include` and/or
1542
+ # Used internally to extend a group with modules using `include`, `prepend` and/or
1008
1543
  # `extend`.
1009
1544
  def configure_group(group)
1010
- include_or_extend_modules.each do |include_or_extend, mod, filters|
1011
- next unless filters.empty? || group.any_apply?(filters)
1012
- __send__("safe_#{include_or_extend}", mod, group)
1013
- end
1545
+ group.hooks.register_globals(group, hooks)
1546
+
1547
+ configure_group_with group, @include_modules, :safe_include
1548
+ configure_group_with group, @extend_modules, :safe_extend
1549
+ configure_group_with group, @prepend_modules, :safe_prepend
1014
1550
  end
1015
1551
 
1016
1552
  # @private
1017
- def safe_include(mod, host)
1018
- host.__send__(:include, mod) unless host < mod
1553
+ #
1554
+ # Used internally to extend the singleton class of a single example's
1555
+ # example group instance with modules using `include` and/or `extend`.
1556
+ def configure_example(example, example_hooks)
1557
+ example_hooks.register_global_singleton_context_hooks(example, hooks)
1558
+ singleton_group = example.example_group_instance.singleton_class
1559
+
1560
+ # We replace the metadata so that SharedExampleGroupModule#included
1561
+ # has access to the example's metadata[:location].
1562
+ singleton_group.with_replaced_metadata(example.metadata) do
1563
+ modules = @include_modules.items_for(example.metadata)
1564
+ modules.each do |mod|
1565
+ safe_include(mod, example.example_group_instance.singleton_class)
1566
+ end
1567
+
1568
+ MemoizedHelpers.define_helpers_on(singleton_group) unless modules.empty?
1569
+ end
1019
1570
  end
1020
1571
 
1021
1572
  # @private
1022
1573
  def requires=(paths)
1023
1574
  directories = ['lib', default_path].select { |p| File.directory? p }
1024
1575
  RSpec::Core::RubyProject.add_to_load_path(*directories)
1025
- paths.each {|path| require path}
1576
+ paths.each { |path| load_file_handling_errors(:require, path) }
1026
1577
  @requires += paths
1027
1578
  end
1028
1579
 
1029
1580
  # @private
1030
- if RUBY_VERSION.to_f >= 1.9
1031
- # @private
1032
- def safe_extend(mod, host)
1033
- host.extend(mod) unless host.singleton_class < mod
1034
- end
1035
- else
1036
- # @private
1037
- def safe_extend(mod, host)
1038
- host.extend(mod) unless (class << host; self; end).included_modules.include?(mod)
1581
+ def in_project_source_dir_regex
1582
+ regexes = project_source_dirs.map do |dir|
1583
+ /\A#{Regexp.escape(File.expand_path(dir))}\//
1039
1584
  end
1585
+
1586
+ Regexp.union(regexes)
1040
1587
  end
1041
1588
 
1042
1589
  # @private
@@ -1055,7 +1602,22 @@ module RSpec
1055
1602
 
1056
1603
  # @private
1057
1604
  def load_spec_files
1058
- files_to_run.uniq.each {|f| load File.expand_path(f) }
1605
+ # Note which spec files world is already aware of.
1606
+ # This is generally only needed for when the user runs
1607
+ # `ruby path/to/spec.rb` (and loads `rspec/autorun`) --
1608
+ # in that case, the spec file was loaded by `ruby` and
1609
+ # isn't loaded by us here so we only know about it because
1610
+ # of an example group being registered in it.
1611
+ world.registered_example_group_files.each do |f|
1612
+ loaded_spec_files << f # the registered files are already expended absolute paths
1613
+ end
1614
+
1615
+ files_to_run.uniq.each do |f|
1616
+ file = File.expand_path(f)
1617
+ load_file_handling_errors(:load, file)
1618
+ loaded_spec_files << file
1619
+ end
1620
+
1059
1621
  @spec_files_loaded = true
1060
1622
  end
1061
1623
 
@@ -1065,7 +1627,8 @@ module RSpec
1065
1627
  # Formats the docstring output using the block provided.
1066
1628
  #
1067
1629
  # @example
1068
- # # This will strip the descriptions of both examples and example groups.
1630
+ # # This will strip the descriptions of both examples and example
1631
+ # # groups.
1069
1632
  # RSpec.configure do |config|
1070
1633
  # config.format_docstrings { |s| s.strip }
1071
1634
  # end
@@ -1079,8 +1642,6 @@ module RSpec
1079
1642
  end
1080
1643
 
1081
1644
  # @private
1082
- # @macro [attach] delegate_to_ordering_manager
1083
- # @!method $1
1084
1645
  def self.delegate_to_ordering_manager(*methods)
1085
1646
  methods.each do |method|
1086
1647
  define_method method do |*args, &block|
@@ -1089,12 +1650,12 @@ module RSpec
1089
1650
  end
1090
1651
  end
1091
1652
 
1092
- # @macro delegate_to_ordering_manager
1653
+ # @!method seed=(value)
1093
1654
  #
1094
1655
  # Sets the seed value and sets the default global ordering to random.
1095
1656
  delegate_to_ordering_manager :seed=
1096
1657
 
1097
- # @macro delegate_to_ordering_manager
1658
+ # @!method seed
1098
1659
  # Seed for random ordering (default: generated randomly each run).
1099
1660
  #
1100
1661
  # When you run specs with `--order random`, RSpec generates a random seed
@@ -1108,20 +1669,28 @@ module RSpec
1108
1669
  # don't accidentally leave the seed encoded.
1109
1670
  delegate_to_ordering_manager :seed
1110
1671
 
1111
- # @macro delegate_to_ordering_manager
1672
+ # @!method order=(value)
1673
+ #
1674
+ # Sets the default global ordering strategy. By default this can be one
1675
+ # of `:defined`, `:random`, but is customizable through the
1676
+ # `register_ordering` API. If order is set to `'rand:<seed>'`,
1677
+ # the seed will also be set.
1112
1678
  #
1113
- # Sets the default global order and, if order is `'rand:<seed>'`, also sets the seed.
1679
+ # @see #register_ordering
1114
1680
  delegate_to_ordering_manager :order=
1115
1681
 
1116
- # @macro delegate_to_ordering_manager
1682
+ # @!method register_ordering(name)
1683
+ #
1117
1684
  # Registers a named ordering strategy that can later be
1118
1685
  # used to order an example group's subgroups by adding
1119
1686
  # `:order => <name>` metadata to the example group.
1120
1687
  #
1121
1688
  # @param name [Symbol] The name of the ordering.
1122
1689
  # @yield Block that will order the given examples or example groups
1123
- # @yieldparam list [Array<RSpec::Core::Example>, Array<RSpec::Core::ExampleGroup>] The examples or groups to order
1124
- # @yieldreturn [Array<RSpec::Core::Example>, Array<RSpec::Core::ExampleGroup>] The re-ordered examples or groups
1690
+ # @yieldparam list [Array<RSpec::Core::Example>,
1691
+ # Array<RSpec::Core::ExampleGroup>] The examples or groups to order
1692
+ # @yieldreturn [Array<RSpec::Core::Example>,
1693
+ # Array<RSpec::Core::ExampleGroup>] The re-ordered examples or groups
1125
1694
  #
1126
1695
  # @example
1127
1696
  # RSpec.configure do |rspec|
@@ -1130,19 +1699,38 @@ module RSpec
1130
1699
  # end
1131
1700
  # end
1132
1701
  #
1133
- # describe MyClass, :order => :reverse do
1702
+ # RSpec.describe 'MyClass', :order => :reverse do
1134
1703
  # # ...
1135
1704
  # end
1136
1705
  #
1137
1706
  # @note Pass the symbol `:global` to set the ordering strategy that
1138
1707
  # will be used to order the top-level example groups and any example
1139
1708
  # groups that do not have declared `:order` metadata.
1709
+ #
1710
+ # @example
1711
+ # RSpec.configure do |rspec|
1712
+ # rspec.register_ordering :global do |examples|
1713
+ # acceptance, other = examples.partition do |example|
1714
+ # example.metadata[:type] == :acceptance
1715
+ # end
1716
+ # other + acceptance
1717
+ # end
1718
+ # end
1719
+ #
1720
+ # RSpec.describe 'MyClass', :type => :acceptance do
1721
+ # # will run last
1722
+ # end
1723
+ #
1724
+ # RSpec.describe 'MyClass' do
1725
+ # # will run first
1726
+ # end
1727
+ #
1140
1728
  delegate_to_ordering_manager :register_ordering
1141
1729
 
1142
1730
  # @private
1143
1731
  delegate_to_ordering_manager :seed_used?, :ordering_registry
1144
1732
 
1145
- # Set Ruby warnings on or off
1733
+ # Set Ruby warnings on or off.
1146
1734
  def warnings=(value)
1147
1735
  $VERBOSE = !!value
1148
1736
  end
@@ -1152,6 +1740,25 @@ module RSpec
1152
1740
  $VERBOSE
1153
1741
  end
1154
1742
 
1743
+ # @private
1744
+ RAISE_ERROR_WARNING_NOTIFIER = lambda { |message| raise message }
1745
+
1746
+ # Turns warnings into errors. This can be useful when
1747
+ # you want RSpec to run in a 'strict' no warning situation.
1748
+ #
1749
+ # @example
1750
+ #
1751
+ # RSpec.configure do |rspec|
1752
+ # rspec.raise_on_warning = true
1753
+ # end
1754
+ def raise_on_warning=(value)
1755
+ if value
1756
+ RSpec::Support.warning_notifier = RAISE_ERROR_WARNING_NOTIFIER
1757
+ else
1758
+ RSpec::Support.warning_notifier = RSpec::Support::DEFAULT_WARNING_NOTIFIER
1759
+ end
1760
+ end
1761
+
1155
1762
  # Exposes the current running example via the named
1156
1763
  # helper method. RSpec 2.x exposed this via `example`,
1157
1764
  # but in RSpec 3.0, the example is instead exposed via
@@ -1168,7 +1775,7 @@ module RSpec
1168
1775
  # rspec.expose_current_running_example_as :example
1169
1776
  # end
1170
1777
  #
1171
- # describe MyClass do
1778
+ # RSpec.describe MyClass do
1172
1779
  # before do
1173
1780
  # # `example` can be used here because of the above config.
1174
1781
  # do_something if example.metadata[:type] == "foo"
@@ -1205,7 +1812,7 @@ module RSpec
1205
1812
  # `shared_examples_for`, etc) onto `main` and `Module`, instead
1206
1813
  # requiring you to prefix these methods with `RSpec.`. It enables
1207
1814
  # expect-only syntax for rspec-mocks and rspec-expectations. It
1208
- # simply disables monkey patching on whatever pieces of rspec
1815
+ # simply disables monkey patching on whatever pieces of RSpec
1209
1816
  # the user is using.
1210
1817
  #
1211
1818
  # @note It configures rspec-mocks and rspec-expectations only
@@ -1213,12 +1820,12 @@ module RSpec
1213
1820
  # by not setting `mock_with` or `expect_with` to anything else).
1214
1821
  #
1215
1822
  # @note If the user uses this options with `mock_with :mocha`
1216
- # (or similiar) they will still have monkey patching active
1823
+ # (or similar) they will still have monkey patching active
1217
1824
  # in their test environment from mocha.
1218
1825
  #
1219
1826
  # @example
1220
1827
  #
1221
- # # It disables all monkey patching
1828
+ # # It disables all monkey patching.
1222
1829
  # RSpec.configure do |config|
1223
1830
  # config.disable_monkey_patching!
1224
1831
  # end
@@ -1232,7 +1839,7 @@ module RSpec
1232
1839
  # mocks.patch_marshal_to_support_partial_doubles = false
1233
1840
  # end
1234
1841
  #
1235
- # config.mock_with :rspec do |expectations|
1842
+ # config.expect_with :rspec do |expectations|
1236
1843
  # expectations.syntax = :expect
1237
1844
  # end
1238
1845
  # end
@@ -1248,73 +1855,423 @@ module RSpec
1248
1855
 
1249
1856
  # Defines a callback that can assign derived metadata values.
1250
1857
  #
1251
- # @param filters [Array<Symbol>, Hash] metadata filters that determine which example
1252
- # or group metadata hashes the callback will be triggered for. If none are given,
1253
- # the callback will be run against the metadata hashes of all groups and examples.
1254
- # @yieldparam metadata [Hash] original metadata hash from an example or group. Mutate this in
1255
- # your block as needed.
1858
+ # @param filters [Array<Symbol>, Hash] metadata filters that determine
1859
+ # which example or group metadata hashes the callback will be triggered
1860
+ # for. If none are given, the callback will be run against the metadata
1861
+ # hashes of all groups and examples.
1862
+ # @yieldparam metadata [Hash] original metadata hash from an example or
1863
+ # group. Mutate this in your block as needed.
1256
1864
  #
1257
1865
  # @example
1258
1866
  # RSpec.configure do |config|
1259
- # # Tag all groups and examples in the spec/unit directory with :type => :unit
1867
+ # # Tag all groups and examples in the spec/unit directory with
1868
+ # # :type => :unit
1260
1869
  # config.define_derived_metadata(:file_path => %r{/spec/unit/}) do |metadata|
1261
1870
  # metadata[:type] = :unit
1262
1871
  # end
1263
1872
  # end
1264
1873
  def define_derived_metadata(*filters, &block)
1265
1874
  meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1266
- @derived_metadata_blocks << [meta, block]
1875
+ @derived_metadata_blocks.append(block, meta)
1876
+ end
1877
+
1878
+ # Defines a callback that runs after the first example with matching
1879
+ # metadata is defined. If no examples are defined with matching metadata,
1880
+ # it will not get called at all.
1881
+ #
1882
+ # This can be used to ensure some setup is performed (such as bootstrapping
1883
+ # a DB or loading a specific file that adds significantly to the boot time)
1884
+ # if needed (as indicated by the presence of an example with matching metadata)
1885
+ # but avoided otherwise.
1886
+ #
1887
+ # @example
1888
+ # RSpec.configure do |config|
1889
+ # config.when_first_matching_example_defined(:db) do
1890
+ # # Load a support file that does some heavyweight setup,
1891
+ # # including bootstrapping the DB, but only if we have loaded
1892
+ # # any examples tagged with `:db`.
1893
+ # require 'support/db'
1894
+ # end
1895
+ # end
1896
+ def when_first_matching_example_defined(*filters)
1897
+ specified_meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1898
+
1899
+ callback = lambda do |example_or_group_meta|
1900
+ # Example groups do not have `:example_group` metadata
1901
+ # (instead they have `:parent_example_group` metadata).
1902
+ return unless example_or_group_meta.key?(:example_group)
1903
+
1904
+ # Ensure the callback only fires once.
1905
+ @derived_metadata_blocks.delete(callback, specified_meta)
1906
+
1907
+ yield
1908
+ end
1909
+
1910
+ @derived_metadata_blocks.append(callback, specified_meta)
1267
1911
  end
1268
1912
 
1269
1913
  # @private
1270
1914
  def apply_derived_metadata_to(metadata)
1271
- @derived_metadata_blocks.each do |filter, block|
1272
- block.call(metadata) if filter.empty? || MetadataFilter.any_apply?(filter, metadata)
1915
+ already_run_blocks = Set.new
1916
+
1917
+ # We loop and attempt to re-apply metadata blocks to support cascades
1918
+ # (e.g. where a derived bit of metadata triggers the application of
1919
+ # another piece of derived metadata, etc)
1920
+ #
1921
+ # We limit our looping to 200 times as a way to detect infinitely recursing derived metadata blocks.
1922
+ # It's hard to imagine a valid use case for a derived metadata cascade greater than 200 iterations.
1923
+ 200.times do
1924
+ return if @derived_metadata_blocks.items_for(metadata).all? do |block|
1925
+ already_run_blocks.include?(block).tap do |skip_block|
1926
+ block.call(metadata) unless skip_block
1927
+ already_run_blocks << block
1928
+ end
1929
+ end
1930
+ end
1931
+
1932
+ # If we got here, then `@derived_metadata_blocks.items_for(metadata).all?` never returned
1933
+ # `true` above and we treat this as an attempt to recurse infinitely. It's better to fail
1934
+ # with a clear # error than hang indefinitely, which is what would happen if we didn't limit
1935
+ # the looping above.
1936
+ raise SystemStackError, "Attempted to recursively derive metadata indefinitely."
1937
+ end
1938
+
1939
+ # Defines a `before` hook. See {Hooks#before} for full docs.
1940
+ #
1941
+ # This method differs from {Hooks#before} in only one way: it supports
1942
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once before
1943
+ # the first example of the entire suite is executed. Conditions passed along
1944
+ # with `:suite` are effectively ignored.
1945
+ #
1946
+ # @see #prepend_before
1947
+ # @see #after
1948
+ # @see #append_after
1949
+ def before(scope=nil, *meta, &block)
1950
+ handle_suite_hook(scope, meta) do
1951
+ @before_suite_hooks << Hooks::BeforeHook.new(block, {})
1952
+ end || begin
1953
+ # defeat Ruby 2.5 lazy proc allocation to ensure
1954
+ # the methods below are passed the same proc instances
1955
+ # so `Hook` equality is preserved. For more info, see:
1956
+ # https://bugs.ruby-lang.org/issues/14045#note-5
1957
+ block.__id__
1958
+
1959
+ add_hook_to_existing_matching_groups(meta, scope) { |g| g.before(scope, *meta, &block) }
1960
+ super(scope, *meta, &block)
1961
+ end
1962
+ end
1963
+ alias_method :append_before, :before
1964
+
1965
+ # Adds `block` to the start of the list of `before` blocks in the same
1966
+ # scope (`:example`, `:context`, or `:suite`), in contrast to {#before},
1967
+ # which adds the hook to the end of the list.
1968
+ #
1969
+ # See {Hooks#before} for full `before` hook docs.
1970
+ #
1971
+ # This method differs from {Hooks#prepend_before} in only one way: it supports
1972
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once before
1973
+ # the first example of the entire suite is executed. Conditions passed along
1974
+ # with `:suite` are effectively ignored.
1975
+ #
1976
+ # @see #before
1977
+ # @see #after
1978
+ # @see #append_after
1979
+ def prepend_before(scope=nil, *meta, &block)
1980
+ handle_suite_hook(scope, meta) do
1981
+ @before_suite_hooks.unshift Hooks::BeforeHook.new(block, {})
1982
+ end || begin
1983
+ # defeat Ruby 2.5 lazy proc allocation to ensure
1984
+ # the methods below are passed the same proc instances
1985
+ # so `Hook` equality is preserved. For more info, see:
1986
+ # https://bugs.ruby-lang.org/issues/14045#note-5
1987
+ block.__id__
1988
+
1989
+ add_hook_to_existing_matching_groups(meta, scope) { |g| g.prepend_before(scope, *meta, &block) }
1990
+ super(scope, *meta, &block)
1991
+ end
1992
+ end
1993
+
1994
+ # Defines a `after` hook. See {Hooks#after} for full docs.
1995
+ #
1996
+ # This method differs from {Hooks#after} in only one way: it supports
1997
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once after
1998
+ # the last example of the entire suite is executed. Conditions passed along
1999
+ # with `:suite` are effectively ignored.
2000
+ #
2001
+ # @see #append_after
2002
+ # @see #before
2003
+ # @see #prepend_before
2004
+ def after(scope=nil, *meta, &block)
2005
+ handle_suite_hook(scope, meta) do
2006
+ @after_suite_hooks.unshift Hooks::AfterHook.new(block, {})
2007
+ end || begin
2008
+ # defeat Ruby 2.5 lazy proc allocation to ensure
2009
+ # the methods below are passed the same proc instances
2010
+ # so `Hook` equality is preserved. For more info, see:
2011
+ # https://bugs.ruby-lang.org/issues/14045#note-5
2012
+ block.__id__
2013
+
2014
+ add_hook_to_existing_matching_groups(meta, scope) { |g| g.after(scope, *meta, &block) }
2015
+ super(scope, *meta, &block)
2016
+ end
2017
+ end
2018
+ alias_method :prepend_after, :after
2019
+
2020
+ # Adds `block` to the end of the list of `after` blocks in the same
2021
+ # scope (`:example`, `:context`, or `:suite`), in contrast to {#after},
2022
+ # which adds the hook to the start of the list.
2023
+ #
2024
+ # See {Hooks#after} for full `after` hook docs.
2025
+ #
2026
+ # This method differs from {Hooks#append_after} in only one way: it supports
2027
+ # the `:suite` scope. Hooks with the `:suite` scope will be run once after
2028
+ # the last example of the entire suite is executed. Conditions passed along
2029
+ # with `:suite` are effectively ignored.
2030
+ #
2031
+ # @see #append_after
2032
+ # @see #before
2033
+ # @see #prepend_before
2034
+ def append_after(scope=nil, *meta, &block)
2035
+ handle_suite_hook(scope, meta) do
2036
+ @after_suite_hooks << Hooks::AfterHook.new(block, {})
2037
+ end || begin
2038
+ # defeat Ruby 2.5 lazy proc allocation to ensure
2039
+ # the methods below are passed the same proc instances
2040
+ # so `Hook` equality is preserved. For more info, see:
2041
+ # https://bugs.ruby-lang.org/issues/14045#note-5
2042
+ block.__id__
2043
+
2044
+ add_hook_to_existing_matching_groups(meta, scope) { |g| g.append_after(scope, *meta, &block) }
2045
+ super(scope, *meta, &block)
2046
+ end
2047
+ end
2048
+
2049
+ # Registers `block` as an `around` hook.
2050
+ #
2051
+ # See {Hooks#around} for full `around` hook docs.
2052
+ def around(scope=nil, *meta, &block)
2053
+ # defeat Ruby 2.5 lazy proc allocation to ensure
2054
+ # the methods below are passed the same proc instances
2055
+ # so `Hook` equality is preserved. For more info, see:
2056
+ # https://bugs.ruby-lang.org/issues/14045#note-5
2057
+ block.__id__
2058
+
2059
+ add_hook_to_existing_matching_groups(meta, scope) { |g| g.around(scope, *meta, &block) }
2060
+ super(scope, *meta, &block)
2061
+ end
2062
+
2063
+ # @private
2064
+ def with_suite_hooks
2065
+ return yield if dry_run?
2066
+
2067
+ begin
2068
+ RSpec.current_scope = :before_suite_hook
2069
+ run_suite_hooks("a `before(:suite)` hook", @before_suite_hooks)
2070
+ yield
2071
+ ensure
2072
+ RSpec.current_scope = :after_suite_hook
2073
+ run_suite_hooks("an `after(:suite)` hook", @after_suite_hooks)
2074
+ RSpec.current_scope = :suite
2075
+ end
2076
+ end
2077
+
2078
+ # @private
2079
+ # Holds the various registered hooks. Here we use a FilterableItemRepository
2080
+ # implementation that is specifically optimized for the read/write patterns
2081
+ # of the config object.
2082
+ def hooks
2083
+ @hooks ||= HookCollections.new(self, FilterableItemRepository::QueryOptimized)
2084
+ end
2085
+
2086
+ # Invokes block before defining an example group
2087
+ def on_example_group_definition(&block)
2088
+ on_example_group_definition_callbacks << block
2089
+ end
2090
+
2091
+ # @api private
2092
+ # Returns an array of blocks to call before defining an example group
2093
+ def on_example_group_definition_callbacks
2094
+ @on_example_group_definition_callbacks ||= []
2095
+ end
2096
+
2097
+ # @private
2098
+ def bisect_runner_class
2099
+ @bisect_runner_class ||= begin
2100
+ case bisect_runner
2101
+ when :fork
2102
+ RSpec::Support.require_rspec_core 'bisect/fork_runner'
2103
+ Bisect::ForkRunner
2104
+ when :shell
2105
+ RSpec::Support.require_rspec_core 'bisect/shell_runner'
2106
+ Bisect::ShellRunner
2107
+ else
2108
+ raise "Unsupported value for `bisect_runner` (#{bisect_runner.inspect}). " \
2109
+ "Only `:fork` and `:shell` are supported."
2110
+ end
1273
2111
  end
1274
2112
  end
1275
2113
 
1276
2114
  private
1277
2115
 
2116
+ def load_file_handling_errors(method, file)
2117
+ __send__(method, file)
2118
+ rescue LoadError => ex
2119
+ relative_file = Metadata.relative_path(file)
2120
+ suggestions = DidYouMean.new(relative_file).call
2121
+ reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.#{suggestions}")
2122
+ RSpec.world.wants_to_quit = true
2123
+ rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
2124
+ relative_file = Metadata.relative_path(file)
2125
+ reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.")
2126
+ RSpec.world.wants_to_quit = true
2127
+ rescue SystemExit => ex
2128
+ relative_file = Metadata.relative_path(file)
2129
+ reporter.notify_non_example_exception(
2130
+ ex,
2131
+ "While loading #{relative_file} an `exit` / `raise SystemExit` occurred, RSpec will now quit."
2132
+ )
2133
+ RSpec.world.rspec_is_quitting = true
2134
+ raise ex
2135
+ end
2136
+
2137
+ def handle_suite_hook(scope, meta)
2138
+ return nil unless scope == :suite
2139
+
2140
+ unless meta.empty?
2141
+ # TODO: in RSpec 4, consider raising an error here.
2142
+ # We warn only for backwards compatibility.
2143
+ RSpec.warn_with "WARNING: `:suite` hooks do not support metadata since " \
2144
+ "they apply to the suite as a whole rather than " \
2145
+ "any individual example or example group that has metadata. " \
2146
+ "The metadata you have provided (#{meta.inspect}) will be ignored."
2147
+ end
2148
+
2149
+ yield
2150
+ end
2151
+
2152
+ def run_suite_hooks(hook_description, hooks)
2153
+ context = SuiteHookContext.new(hook_description, reporter)
2154
+
2155
+ hooks.each do |hook|
2156
+ begin
2157
+ hook.run(context)
2158
+ rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
2159
+ context.set_exception(ex)
2160
+
2161
+ # Do not run subsequent `before` hooks if one fails.
2162
+ # But for `after` hooks, we run them all so that all
2163
+ # cleanup bits get a chance to complete, minimizing the
2164
+ # chance that resources get left behind.
2165
+ break if hooks.equal?(@before_suite_hooks)
2166
+ end
2167
+ end
2168
+ end
2169
+
1278
2170
  def get_files_to_run(paths)
1279
- FlatMap.flat_map(paths) do |path|
2171
+ files = FlatMap.flat_map(paths_to_check(paths)) do |path|
1280
2172
  path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
1281
2173
  File.directory?(path) ? gather_directories(path) : extract_location(path)
1282
- end.sort
2174
+ end.uniq
2175
+
2176
+ return files unless only_failures?
2177
+ relative_files = files.map { |f| Metadata.relative_path(File.expand_path f) }
2178
+ intersection = (relative_files & spec_files_with_failures.to_a)
2179
+ intersection.empty? ? files : intersection
2180
+ end
2181
+
2182
+ def paths_to_check(paths)
2183
+ return paths if pattern_might_load_specs_from_vendored_dirs?
2184
+ paths + [Dir.getwd]
2185
+ end
2186
+
2187
+ def pattern_might_load_specs_from_vendored_dirs?
2188
+ pattern.split(File::SEPARATOR).first.include?('**')
1283
2189
  end
1284
2190
 
1285
2191
  def gather_directories(path)
2192
+ include_files = get_matching_files(path, pattern)
2193
+ exclude_files = get_matching_files(path, exclude_pattern)
2194
+ (include_files - exclude_files).uniq
2195
+ end
2196
+
2197
+ def get_matching_files(path, pattern)
2198
+ raw_files = Dir[file_glob_from(path, pattern)]
2199
+ raw_files.map { |file| File.expand_path(file) }.sort
2200
+ end
2201
+
2202
+ def file_glob_from(path, pattern)
1286
2203
  stripped = "{#{pattern.gsub(/\s*,\s*/, ',')}}"
1287
- files = pattern =~ /^#{Regexp.escape path}/ ? Dir[stripped] : Dir["#{path}/#{stripped}"]
1288
- files.sort
2204
+ return stripped if pattern =~ /^(\.\/)?#{Regexp.escape path}/ || absolute_pattern?(pattern)
2205
+ File.join(path, stripped)
2206
+ end
2207
+
2208
+ if RSpec::Support::OS.windows?
2209
+ # :nocov:
2210
+ def absolute_pattern?(pattern)
2211
+ pattern =~ /\A[A-Z]:\\/ || windows_absolute_network_path?(pattern)
2212
+ end
2213
+
2214
+ def windows_absolute_network_path?(pattern)
2215
+ return false unless ::File::ALT_SEPARATOR
2216
+ pattern.start_with?(::File::ALT_SEPARATOR + ::File::ALT_SEPARATOR)
2217
+ end
2218
+ # :nocov:
2219
+ else
2220
+ def absolute_pattern?(pattern)
2221
+ pattern.start_with?(File::Separator)
2222
+ end
1289
2223
  end
1290
2224
 
1291
2225
  def extract_location(path)
1292
- if path =~ /^(.*?)((?:\:\d+)+)$/
1293
- path, lines = $1, $2[1..-1].split(":").map{|n| n.to_i}
2226
+ match = /^(.*?)((?:\:\d+)+)$/.match(path)
2227
+
2228
+ if match
2229
+ captures = match.captures
2230
+ path = captures[0]
2231
+ lines = captures[1][1..-1].split(":").map(&:to_i)
1294
2232
  filter_manager.add_location path, lines
2233
+ else
2234
+ path, scoped_ids = Example.parse_id(path)
2235
+ filter_manager.add_ids(path, scoped_ids.split(/\s*,\s*/)) if scoped_ids
1295
2236
  end
1296
- path
2237
+
2238
+ return [] if path == default_path
2239
+ File.expand_path(path)
1297
2240
  end
1298
2241
 
1299
2242
  def command
1300
2243
  $0.split(File::SEPARATOR).last
1301
2244
  end
1302
2245
 
1303
- def value_for(key, default=nil)
1304
- @preferred_options.has_key?(key) ? @preferred_options[key] : default
2246
+ def value_for(key)
2247
+ @preferred_options.fetch(key) { yield }
1305
2248
  end
1306
2249
 
1307
- def assert_no_example_groups_defined(config_option)
1308
- if RSpec.world.example_groups.any?
1309
- raise MustBeConfiguredBeforeExampleGroupsError.new(
1310
- "RSpec's #{config_option} configuration option must be configured before " +
1311
- "any example groups are defined, but you have already defined a group."
1312
- )
2250
+ def define_built_in_hooks
2251
+ around(:example, :aggregate_failures => true) do |procsy|
2252
+ begin
2253
+ aggregate_failures(nil, :hide_backtrace => true, &procsy)
2254
+ rescue Support::AllExceptionsExceptOnesWeMustNotRescue => exception
2255
+ procsy.example.set_aggregate_failures_exception(exception)
2256
+ end
1313
2257
  end
1314
2258
  end
1315
2259
 
2260
+ def assert_no_example_groups_defined(config_option)
2261
+ return unless world.example_groups.any?
2262
+
2263
+ raise MustBeConfiguredBeforeExampleGroupsError.new(
2264
+ "RSpec's #{config_option} configuration option must be configured before " \
2265
+ "any example groups are defined, but you have already defined a group."
2266
+ )
2267
+ end
2268
+
2269
+ def output_wrapper
2270
+ @output_wrapper ||= OutputWrapper.new(output_stream)
2271
+ end
2272
+
1316
2273
  def output_to_tty?(output=output_stream)
1317
- tty? || (output.respond_to?(:tty?) && output.tty?)
2274
+ output.respond_to?(:tty?) && output.tty?
1318
2275
  end
1319
2276
 
1320
2277
  def conditionally_disable_mocks_monkey_patching
@@ -1339,6 +2296,90 @@ module RSpec
1339
2296
  def rspec_expectations_loaded?
1340
2297
  defined?(RSpec::Expectations.configuration)
1341
2298
  end
2299
+
2300
+ def update_pattern_attr(name, value)
2301
+ if @spec_files_loaded
2302
+ RSpec.warning "Configuring `#{name}` to #{value} has no effect since " \
2303
+ "RSpec has already loaded the spec files."
2304
+ end
2305
+
2306
+ instance_variable_set(:"@#{name}", value)
2307
+ @files_to_run = nil
2308
+ end
2309
+
2310
+ def clear_values_derived_from_example_status_persistence_file_path
2311
+ @last_run_statuses = nil
2312
+ @spec_files_with_failures = nil
2313
+ end
2314
+
2315
+ def configure_group_with(group, module_list, application_method)
2316
+ module_list.items_for(group.metadata).each do |mod|
2317
+ __send__(application_method, mod, group)
2318
+ end
2319
+ end
2320
+
2321
+ def add_hook_to_existing_matching_groups(meta, scope, &block)
2322
+ # For example hooks, we have to apply it to each of the top level
2323
+ # groups, even if the groups do not match. When we apply it, we
2324
+ # apply it with the metadata, so it will only apply to examples
2325
+ # in the group that match the metadata.
2326
+ # #2280 for background and discussion.
2327
+ if scope == :example || scope == :each || scope.nil?
2328
+ world.example_groups.each(&block)
2329
+ else
2330
+ meta = Metadata.build_hash_from(meta.dup)
2331
+ on_existing_matching_groups(meta, &block)
2332
+ end
2333
+ end
2334
+
2335
+ def on_existing_matching_groups(meta)
2336
+ world.traverse_example_group_trees_until do |group|
2337
+ metadata_applies_to_group?(meta, group).tap do |applies|
2338
+ yield group if applies
2339
+ end
2340
+ end
2341
+ end
2342
+
2343
+ def metadata_applies_to_group?(meta, group)
2344
+ meta.empty? || MetadataFilter.apply?(:any?, meta, group.metadata)
2345
+ end
2346
+
2347
+ if RSpec::Support::RubyFeatures.module_prepends_supported?
2348
+ def safe_prepend(mod, host)
2349
+ host.__send__(:prepend, mod) unless host < mod
2350
+ end
2351
+ end
2352
+
2353
+ if RUBY_VERSION.to_f >= 1.9
2354
+ def safe_include(mod, host)
2355
+ host.__send__(:include, mod) unless host < mod
2356
+ end
2357
+
2358
+ def safe_extend(mod, host)
2359
+ host.extend(mod) unless host.singleton_class < mod
2360
+ end
2361
+ else # for 1.8.7
2362
+ # :nocov:
2363
+ def safe_include(mod, host)
2364
+ host.__send__(:include, mod) unless host.included_modules.include?(mod)
2365
+ end
2366
+
2367
+ def safe_extend(mod, host)
2368
+ host.extend(mod) unless (class << host; self; end).included_modules.include?(mod)
2369
+ end
2370
+ # :nocov:
2371
+ end
2372
+
2373
+ def define_mixed_in_module(mod, filters, mod_list, config_method, &block)
2374
+ unless Module === mod
2375
+ raise TypeError, "`RSpec.configuration.#{config_method}` expects a module but got: #{mod.inspect}"
2376
+ end
2377
+
2378
+ meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
2379
+ mod_list.append(mod, meta)
2380
+ on_existing_matching_groups(meta, &block)
2381
+ end
1342
2382
  end
2383
+ # rubocop:enable Metrics/ClassLength
1343
2384
  end
1344
2385
  end