rspec-core 3.7.0 → 3.8.0

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 (38) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +36 -2
  4. data/README.md +1 -1
  5. data/lib/rspec/core/bisect/coordinator.rb +26 -30
  6. data/lib/rspec/core/bisect/example_minimizer.rb +12 -8
  7. data/lib/rspec/core/bisect/fork_runner.rb +134 -0
  8. data/lib/rspec/core/bisect/server.rb +4 -13
  9. data/lib/rspec/core/bisect/{runner.rb → shell_command.rb} +27 -70
  10. data/lib/rspec/core/bisect/shell_runner.rb +73 -0
  11. data/lib/rspec/core/bisect/utilities.rb +58 -0
  12. data/lib/rspec/core/configuration.rb +163 -53
  13. data/lib/rspec/core/configuration_options.rb +41 -4
  14. data/lib/rspec/core/example.rb +4 -4
  15. data/lib/rspec/core/example_group.rb +1 -0
  16. data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
  17. data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
  18. data/lib/rspec/core/formatters/bisect_progress_formatter.rb +29 -16
  19. data/lib/rspec/core/formatters/deprecation_formatter.rb +3 -1
  20. data/lib/rspec/core/formatters/exception_presenter.rb +1 -0
  21. data/lib/rspec/core/formatters/html_printer.rb +0 -2
  22. data/lib/rspec/core/formatters/protocol.rb +17 -17
  23. data/lib/rspec/core/formatters/syntax_highlighter.rb +19 -19
  24. data/lib/rspec/core/formatters.rb +10 -6
  25. data/lib/rspec/core/hooks.rb +1 -3
  26. data/lib/rspec/core/invocations.rb +8 -6
  27. data/lib/rspec/core/memoized_helpers.rb +2 -2
  28. data/lib/rspec/core/profiler.rb +3 -1
  29. data/lib/rspec/core/reporter.rb +3 -6
  30. data/lib/rspec/core/runner.rb +20 -14
  31. data/lib/rspec/core/shared_example_group.rb +1 -3
  32. data/lib/rspec/core/shell_escape.rb +2 -2
  33. data/lib/rspec/core/version.rb +1 -1
  34. data/lib/rspec/core/world.rb +11 -0
  35. data.tar.gz.sig +0 -0
  36. metadata +12 -9
  37. metadata.gz.sig +0 -0
  38. data/lib/rspec/core/formatters/bisect_formatter.rb +0 -69
@@ -9,10 +9,24 @@ module RSpec
9
9
 
10
10
  # Stores runtime configuration information.
11
11
  #
12
- # Configuration options are loaded from `~/.rspec`, `.rspec`,
13
- # `.rspec-local`, command line switches, and the `SPEC_OPTS` environment
14
- # variable (listed in lowest to highest precedence; for example, an option
15
- # 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.
16
30
  #
17
31
  # @example Standard settings
18
32
  # RSpec.configure do |c|
@@ -89,7 +103,6 @@ module RSpec
89
103
 
90
104
  # @macro [attach] add_setting
91
105
  # @!attribute [rw] $1
92
- # @!method $1=(value)
93
106
  #
94
107
  # @macro [attach] define_reader
95
108
  # @!attribute [r] $1
@@ -101,6 +114,7 @@ module RSpec
101
114
  #
102
115
  # @note Other scripts invoking `rspec` indirectly will ignore this
103
116
  # setting.
117
+ # @return [String]
104
118
  add_read_only_setting :default_path
105
119
  def default_path=(path)
106
120
  project_source_dirs << path
@@ -110,6 +124,7 @@ module RSpec
110
124
  # @macro add_setting
111
125
  # Run examples over DRb (default: `false`). RSpec doesn't supply the DRb
112
126
  # server, but you can use tools like spork.
127
+ # @return [Boolean]
113
128
  add_setting :drb
114
129
 
115
130
  # @macro add_setting
@@ -122,6 +137,7 @@ module RSpec
122
137
 
123
138
  # Indicates if the DSL has been exposed off of modules and `main`.
124
139
  # Default: true
140
+ # @return [Boolean]
125
141
  def expose_dsl_globally?
126
142
  Core::DSL.exposed_globally?
127
143
  end
@@ -198,24 +214,29 @@ module RSpec
198
214
 
199
215
  # @macro add_setting
200
216
  # The exit code to return if there are any failures (default: 1).
217
+ # @return [Integer]
201
218
  add_setting :failure_exit_code
202
219
 
203
220
  # @macro add_setting
204
221
  # Whether or not to fail when there are no RSpec examples (default: false).
222
+ # @return [Boolean]
205
223
  add_setting :fail_if_no_examples
206
224
 
207
225
  # @macro define_reader
208
226
  # Indicates files configured to be required.
227
+ # @return [Array<String>]
209
228
  define_reader :requires
210
229
 
211
230
  # @macro define_reader
212
231
  # Returns dirs that have been prepended to the load path by the `-I`
213
232
  # command line option.
233
+ # @return [Array<String>]
214
234
  define_reader :libs
215
235
 
216
236
  # @macro add_setting
217
237
  # Determines where RSpec will send its output.
218
238
  # Default: `$stdout`.
239
+ # @return [IO, String]
219
240
  define_reader :output_stream
220
241
 
221
242
  # Set the output stream for reporter.
@@ -234,6 +255,7 @@ module RSpec
234
255
 
235
256
  # @macro define_reader
236
257
  # Load files matching this pattern (default: `'**{,/*/**}/*_spec.rb'`).
258
+ # @return [String]
237
259
  define_reader :pattern
238
260
 
239
261
  # Set pattern to match files to load.
@@ -244,6 +266,7 @@ module RSpec
244
266
 
245
267
  # @macro define_reader
246
268
  # Exclude files matching this pattern.
269
+ # @return [String]
247
270
  define_reader :exclude_pattern
248
271
 
249
272
  # Set pattern to match files to exclude.
@@ -265,6 +288,7 @@ module RSpec
265
288
  # @macro add_setting
266
289
  # Report the times for the slowest examples (default: `false`).
267
290
  # Use this to specify the number of examples to include in the profile.
291
+ # @return [Boolean]
268
292
  add_setting :profile_examples
269
293
 
270
294
  # @macro add_setting
@@ -275,55 +299,56 @@ module RSpec
275
299
  add_setting :run_all_when_everything_filtered
276
300
 
277
301
  # @macro add_setting
278
- # Color to use to indicate success.
279
- # @param color [Symbol] defaults to `:green` but can be set to one of the
280
- # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
281
- # :cyan]`
302
+ # Color to use to indicate success. Defaults to `:green` but can be set
303
+ # to one of the following: `[:black, :white, :red, :green, :yellow,
304
+ # :blue, :magenta, :cyan]`
305
+ # @return [Symbol]
282
306
  add_setting :success_color
283
307
 
284
308
  # @macro add_setting
285
- # Color to use to print pending examples.
286
- # @param color [Symbol] defaults to `:yellow` but can be set to one of the
287
- # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
288
- # :cyan]`
309
+ # Color to use to print pending examples. Defaults to `:yellow` but can
310
+ # be set to one of the following: `[:black, :white, :red, :green,
311
+ # :yellow, :blue, :magenta, :cyan]`
312
+ # @return [Symbol]
289
313
  add_setting :pending_color
290
314
 
291
315
  # @macro add_setting
292
- # Color to use to indicate failure.
293
- # @param color [Symbol] defaults to `:red` but can be set to one of the
294
- # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
295
- # :cyan]`
316
+ # Color to use to indicate failure. Defaults to `:red` but can be set to
317
+ # one of the following: `[:black, :white, :red, :green, :yellow, :blue,
318
+ # :magenta, :cyan]`
319
+ # @return [Symbol]
296
320
  add_setting :failure_color
297
321
 
298
322
  # @macro add_setting
299
- # The default output color.
300
- # @param color [Symbol] defaults to `:white` but can be set to one of the
301
- # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
302
- # :cyan]`
323
+ # The default output color. Defaults to `:white` but can be set to one of
324
+ # the following: `[:black, :white, :red, :green, :yellow, :blue,
325
+ # :magenta, :cyan]`
326
+ # @return [Symbol]
303
327
  add_setting :default_color
304
328
 
305
329
  # @macro add_setting
306
- # Color used when a pending example is fixed.
307
- # @param color [Symbol] defaults to `:blue` but can be set to one of the
308
- # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
309
- # :cyan]`
330
+ # Color used when a pending example is fixed. Defaults to `:blue` but can
331
+ # be set to one of the following: `[:black, :white, :red, :green,
332
+ # :yellow, :blue, :magenta, :cyan]`
333
+ # @return [Symbol]
310
334
  add_setting :fixed_color
311
335
 
312
336
  # @macro add_setting
313
- # Color used to print details.
314
- # @param color [Symbol] defaults to `:cyan` but can be set to one of the
315
- # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta,
316
- # :cyan]`
337
+ # Color used to print details. Defaults to `:cyan` but can be set to one
338
+ # of the following: `[:black, :white, :red, :green, :yellow, :blue,
339
+ # :magenta, :cyan]`
340
+ # @return [Symbol]
317
341
  add_setting :detail_color
318
342
 
319
343
  # @macro add_setting
320
344
  # Don't print filter info i.e. "Run options: include {:focus=>true}"
321
345
  # (default `false`).
346
+ # return [Boolean]
322
347
  add_setting :silence_filter_announcements
323
348
 
324
- # Deprecated. This config option was added in RSpec 2 to pave the way
325
- # for this being the default behavior in RSpec 3. Now this option is
326
- # a no-op.
349
+ # @deprecated This config option was added in RSpec 2 to pave the way
350
+ # for this being the default behavior in RSpec 3. Now this option is
351
+ # a no-op.
327
352
  def treat_symbols_as_metadata_keys_with_true_values=(_value)
328
353
  RSpec.deprecate(
329
354
  "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=",
@@ -387,18 +412,53 @@ module RSpec
387
412
  end
388
413
 
389
414
  # Record the start time of the spec suite to measure load time.
415
+ # return [Time]
390
416
  add_setting :start_time
391
417
 
392
418
  # @macro add_setting
393
419
  # Use threadsafe options where available.
394
420
  # Currently this will place a mutex around memoized values such as let blocks.
421
+ # return [Boolean]
395
422
  add_setting :threadsafe
396
423
 
397
424
  # @macro add_setting
398
425
  # Maximum count of failed source lines to display in the failure reports.
399
426
  # (default `10`).
427
+ # return [Integer]
400
428
  add_setting :max_displayed_failure_line_count
401
429
 
430
+ # Determines which bisect runner implementation gets used to run subsets
431
+ # of the suite during a bisection. Your choices are:
432
+ #
433
+ # - `:shell`: Performs a spec run by shelling out, booting RSpec and your
434
+ # application environment each time. This runner is the most widely
435
+ # compatible runner, but is not as fast. On platforms that do not
436
+ # support forking, this is the default.
437
+ # - `:fork`: Pre-boots RSpec and your application environment in a parent
438
+ # process, and then forks a child process for each spec run. This runner
439
+ # tends to be significantly faster than the `:shell` runner but cannot
440
+ # be used in some situations. On platforms that support forking, this
441
+ # is the default. If you use this runner, you should ensure that all
442
+ # of your one-time setup logic goes in a `before(:suite)` hook instead
443
+ # of getting run at the top-level of a file loaded by `--require`.
444
+ #
445
+ # @note This option will only be used by `--bisect` if you set it in a file
446
+ # loaded via `--require`.
447
+ #
448
+ # @return [Symbol]
449
+ attr_reader :bisect_runner
450
+ def bisect_runner=(value)
451
+ if @bisect_runner_class && value != @bisect_runner
452
+ raise "`config.bisect_runner = #{value.inspect}` can no longer take " \
453
+ "effect as the #{@bisect_runner.inspect} bisect runnner is already " \
454
+ "in use. This config setting must be set in a file loaded by a " \
455
+ "`--require` option (passed at the CLI or in a `.rspec` file) for " \
456
+ "it to have any effect."
457
+ end
458
+
459
+ @bisect_runner = value
460
+ end
461
+
402
462
  # @private
403
463
  # @deprecated Use {#color_mode} = :on, instead of {#color} with {#tty}
404
464
  add_setting :tty
@@ -411,8 +471,7 @@ module RSpec
411
471
  # @private
412
472
  attr_reader :backtrace_formatter, :ordering_manager, :loaded_spec_files
413
473
 
414
- # rubocop:disable Metrics/AbcSize
415
- # rubocop:disable Metrics/MethodLength
474
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
416
475
 
417
476
  # Build an object to store runtime configuration options and set defaults
418
477
  def initialize
@@ -424,6 +483,9 @@ module RSpec
424
483
  @extend_modules = FilterableItemRepository::QueryOptimized.new(:any?)
425
484
  @prepend_modules = FilterableItemRepository::QueryOptimized.new(:any?)
426
485
 
486
+ @bisect_runner = RSpec::Support::RubyFeatures.fork_supported? ? :fork : :shell
487
+ @bisect_runner_class = nil
488
+
427
489
  @before_suite_hooks = []
428
490
  @after_suite_hooks = []
429
491
 
@@ -467,8 +529,7 @@ module RSpec
467
529
 
468
530
  define_built_in_hooks
469
531
  end
470
- # rubocop:enable Metrics/MethodLength
471
- # rubocop:enable Metrics/AbcSize
532
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
472
533
 
473
534
  # @private
474
535
  #
@@ -549,6 +610,7 @@ module RSpec
549
610
  end
550
611
 
551
612
  # Returns the configured mock framework adapter module.
613
+ # @return [Symbol]
552
614
  def mock_framework
553
615
  if @mock_framework.nil?
554
616
  begin
@@ -576,12 +638,13 @@ module RSpec
576
638
  # To override this behaviour and display a full backtrace, use
577
639
  # `--backtrace` on the command line, in a `.rspec` file, or in the
578
640
  # `rspec_options` attribute of RSpec's rake task.
641
+ # @return [Array<Regexp>]
579
642
  def backtrace_exclusion_patterns
580
643
  @backtrace_formatter.exclusion_patterns
581
644
  end
582
645
 
583
646
  # Set regular expressions used to exclude lines in backtrace.
584
- # @param patterns [Regexp] set the backtrace exlusion pattern
647
+ # @param patterns [Array<Regexp>] set backtrace_formatter exlusion_patterns
585
648
  def backtrace_exclusion_patterns=(patterns)
586
649
  @backtrace_formatter.exclusion_patterns = patterns
587
650
  end
@@ -594,12 +657,13 @@ module RSpec
594
657
  # will be included.
595
658
  #
596
659
  # You can modify the list via the getter, or replace it with the setter.
660
+ # @return [Array<Regexp>]
597
661
  def backtrace_inclusion_patterns
598
662
  @backtrace_formatter.inclusion_patterns
599
663
  end
600
664
 
601
665
  # Set regular expressions used to include lines in backtrace.
602
- # @attr patterns [Regexp] set backtrace_formatter inclusion_patterns
666
+ # @attr patterns [Array<Regexp>] set backtrace_formatter inclusion_patterns
603
667
  def backtrace_inclusion_patterns=(patterns)
604
668
  @backtrace_formatter.inclusion_patterns = patterns
605
669
  end
@@ -862,11 +926,11 @@ module RSpec
862
926
  # @overload add_formatter(formatter)
863
927
  # @overload add_formatter(formatter, output)
864
928
  #
865
- # @param formatter [Class, String] formatter to use. Can be any of the
929
+ # @param formatter [Class, String, Object] formatter to use. Can be any of the
866
930
  # string values supported from the CLI (`p`/`progress`,
867
- # `d`/`doc`/`documentation`, `h`/`html`, or `j`/`json`) or any
931
+ # `d`/`doc`/`documentation`, `h`/`html`, or `j`/`json`), any
868
932
  # class that implements the formatter protocol and has registered
869
- # itself with RSpec as a formatter.
933
+ # itself with RSpec as a formatter, or a formatter instance.
870
934
  # @param output [String, IO] where the formatter will write its output.
871
935
  # Can be an IO object or a string path to a file. If not provided,
872
936
  # the configured `output_stream` (`$stdout`, by default) will be used.
@@ -1452,7 +1516,7 @@ module RSpec
1452
1516
  def requires=(paths)
1453
1517
  directories = ['lib', default_path].select { |p| File.directory? p }
1454
1518
  RSpec::Core::RubyProject.add_to_load_path(*directories)
1455
- paths.each { |path| require path }
1519
+ paths.each { |path| load_file_handling_errors(:require, path) }
1456
1520
  @requires += paths
1457
1521
  end
1458
1522
 
@@ -1493,7 +1557,7 @@ module RSpec
1493
1557
 
1494
1558
  files_to_run.uniq.each do |f|
1495
1559
  file = File.expand_path(f)
1496
- load_spec_file_handling_errors(file)
1560
+ load_file_handling_errors(:load, file)
1497
1561
  loaded_spec_files << file
1498
1562
  end
1499
1563
 
@@ -1521,8 +1585,6 @@ module RSpec
1521
1585
  end
1522
1586
 
1523
1587
  # @private
1524
- # @macro [attach] delegate_to_ordering_manager
1525
- # @!method $1
1526
1588
  def self.delegate_to_ordering_manager(*methods)
1527
1589
  methods.each do |method|
1528
1590
  define_method method do |*args, &block|
@@ -1531,12 +1593,12 @@ module RSpec
1531
1593
  end
1532
1594
  end
1533
1595
 
1534
- # @macro delegate_to_ordering_manager
1596
+ # @!method seed=(value)
1535
1597
  #
1536
1598
  # Sets the seed value and sets the default global ordering to random.
1537
1599
  delegate_to_ordering_manager :seed=
1538
1600
 
1539
- # @macro delegate_to_ordering_manager
1601
+ # @!method seed
1540
1602
  # Seed for random ordering (default: generated randomly each run).
1541
1603
  #
1542
1604
  # When you run specs with `--order random`, RSpec generates a random seed
@@ -1550,7 +1612,7 @@ module RSpec
1550
1612
  # don't accidentally leave the seed encoded.
1551
1613
  delegate_to_ordering_manager :seed
1552
1614
 
1553
- # @macro delegate_to_ordering_manager
1615
+ # @!method order=(value)
1554
1616
  #
1555
1617
  # Sets the default global ordering strategy. By default this can be one
1556
1618
  # of `:defined`, `:random`, but is customizable through the
@@ -1560,7 +1622,8 @@ module RSpec
1560
1622
  # @see #register_ordering
1561
1623
  delegate_to_ordering_manager :order=
1562
1624
 
1563
- # @macro delegate_to_ordering_manager
1625
+ # @!method register_ordering(name)
1626
+ #
1564
1627
  # Registers a named ordering strategy that can later be
1565
1628
  # used to order an example group's subgroups by adding
1566
1629
  # `:order => <name>` metadata to the example group.
@@ -1773,7 +1836,7 @@ module RSpec
1773
1836
  # require 'support/db'
1774
1837
  # end
1775
1838
  # end
1776
- def when_first_matching_example_defined(*filters, &block)
1839
+ def when_first_matching_example_defined(*filters)
1777
1840
  specified_meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1778
1841
 
1779
1842
  callback = lambda do |example_or_group_meta|
@@ -1784,7 +1847,7 @@ module RSpec
1784
1847
  # Ensure the callback only fires once.
1785
1848
  @derived_metadata_blocks.delete(callback, specified_meta)
1786
1849
 
1787
- block.call
1850
+ yield
1788
1851
  end
1789
1852
 
1790
1853
  @derived_metadata_blocks.append(callback, specified_meta)
@@ -1810,6 +1873,12 @@ module RSpec
1810
1873
  handle_suite_hook(scope, meta) do
1811
1874
  @before_suite_hooks << Hooks::BeforeHook.new(block, {})
1812
1875
  end || begin
1876
+ # defeat Ruby 2.5 lazy proc allocation to ensure
1877
+ # the methods below are passed the same proc instances
1878
+ # so `Hook` equality is preserved. For more info, see:
1879
+ # https://bugs.ruby-lang.org/issues/14045#note-5
1880
+ block.__id__
1881
+
1813
1882
  add_hook_to_existing_matching_groups(meta, scope) { |g| g.before(scope, *meta, &block) }
1814
1883
  super(scope, *meta, &block)
1815
1884
  end
@@ -1833,6 +1902,12 @@ module RSpec
1833
1902
  handle_suite_hook(scope, meta) do
1834
1903
  @before_suite_hooks.unshift Hooks::BeforeHook.new(block, {})
1835
1904
  end || begin
1905
+ # defeat Ruby 2.5 lazy proc allocation to ensure
1906
+ # the methods below are passed the same proc instances
1907
+ # so `Hook` equality is preserved. For more info, see:
1908
+ # https://bugs.ruby-lang.org/issues/14045#note-5
1909
+ block.__id__
1910
+
1836
1911
  add_hook_to_existing_matching_groups(meta, scope) { |g| g.prepend_before(scope, *meta, &block) }
1837
1912
  super(scope, *meta, &block)
1838
1913
  end
@@ -1851,6 +1926,12 @@ module RSpec
1851
1926
  handle_suite_hook(scope, meta) do
1852
1927
  @after_suite_hooks.unshift Hooks::AfterHook.new(block, {})
1853
1928
  end || begin
1929
+ # defeat Ruby 2.5 lazy proc allocation to ensure
1930
+ # the methods below are passed the same proc instances
1931
+ # so `Hook` equality is preserved. For more info, see:
1932
+ # https://bugs.ruby-lang.org/issues/14045#note-5
1933
+ block.__id__
1934
+
1854
1935
  add_hook_to_existing_matching_groups(meta, scope) { |g| g.after(scope, *meta, &block) }
1855
1936
  super(scope, *meta, &block)
1856
1937
  end
@@ -1874,6 +1955,12 @@ module RSpec
1874
1955
  handle_suite_hook(scope, meta) do
1875
1956
  @after_suite_hooks << Hooks::AfterHook.new(block, {})
1876
1957
  end || begin
1958
+ # defeat Ruby 2.5 lazy proc allocation to ensure
1959
+ # the methods below are passed the same proc instances
1960
+ # so `Hook` equality is preserved. For more info, see:
1961
+ # https://bugs.ruby-lang.org/issues/14045#note-5
1962
+ block.__id__
1963
+
1877
1964
  add_hook_to_existing_matching_groups(meta, scope) { |g| g.append_after(scope, *meta, &block) }
1878
1965
  super(scope, *meta, &block)
1879
1966
  end
@@ -1883,6 +1970,12 @@ module RSpec
1883
1970
  #
1884
1971
  # See {Hooks#around} for full `around` hook docs.
1885
1972
  def around(scope=nil, *meta, &block)
1973
+ # defeat Ruby 2.5 lazy proc allocation to ensure
1974
+ # the methods below are passed the same proc instances
1975
+ # so `Hook` equality is preserved. For more info, see:
1976
+ # https://bugs.ruby-lang.org/issues/14045#note-5
1977
+ block.__id__
1978
+
1886
1979
  add_hook_to_existing_matching_groups(meta, scope) { |g| g.around(scope, *meta, &block) }
1887
1980
  super(scope, *meta, &block)
1888
1981
  end
@@ -1918,10 +2011,27 @@ module RSpec
1918
2011
  @on_example_group_definition_callbacks ||= []
1919
2012
  end
1920
2013
 
2014
+ # @private
2015
+ def bisect_runner_class
2016
+ @bisect_runner_class ||= begin
2017
+ case bisect_runner
2018
+ when :fork
2019
+ RSpec::Support.require_rspec_core 'bisect/fork_runner'
2020
+ Bisect::ForkRunner
2021
+ when :shell
2022
+ RSpec::Support.require_rspec_core 'bisect/shell_runner'
2023
+ Bisect::ShellRunner
2024
+ else
2025
+ raise "Unsupported value for `bisect_runner` (#{bisect_runner.inspect}). " \
2026
+ "Only `:fork` and `:shell` are supported."
2027
+ end
2028
+ end
2029
+ end
2030
+
1921
2031
  private
1922
2032
 
1923
- def load_spec_file_handling_errors(file)
1924
- load file
2033
+ def load_file_handling_errors(method, file)
2034
+ __send__(method, file)
1925
2035
  rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
1926
2036
  relative_file = Metadata.relative_path(file)
1927
2037
  reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.")
@@ -4,8 +4,9 @@ require 'shellwords'
4
4
  module RSpec
5
5
  module Core
6
6
  # Responsible for utilizing externally provided configuration options,
7
- # whether via the command line, `.rspec`, `~/.rspec`, `.rspec-local`
8
- # or a custom options file.
7
+ # whether via the command line, `.rspec`, `~/.rspec`,
8
+ # `$XDG_CONFIG_HOME/rspec/options`, `.rspec-local` or a custom options
9
+ # file.
9
10
  class ConfigurationOptions
10
11
  # @param args [Array<String>] command line arguments
11
12
  def initialize(args)
@@ -118,7 +119,11 @@ module RSpec
118
119
  end
119
120
 
120
121
  def file_options
121
- custom_options_file ? [custom_options] : [global_options, project_options, local_options]
122
+ if custom_options_file
123
+ [custom_options]
124
+ else
125
+ [global_options, project_options, local_options]
126
+ end
122
127
  end
123
128
 
124
129
  def env_options
@@ -168,7 +173,11 @@ module RSpec
168
173
  end
169
174
 
170
175
  def options_file_as_erb_string(path)
171
- ERB.new(File.read(path), nil, '-').result(binding)
176
+ if RUBY_VERSION >= '2.6'
177
+ ERB.new(File.read(path), :trim_mode => '-').result(binding)
178
+ else
179
+ ERB.new(File.read(path), nil, '-').result(binding)
180
+ end
172
181
  end
173
182
 
174
183
  def custom_options_file
@@ -184,6 +193,17 @@ module RSpec
184
193
  end
185
194
 
186
195
  def global_options_file
196
+ xdg_options_file_if_exists || home_options_file_path
197
+ end
198
+
199
+ def xdg_options_file_if_exists
200
+ path = xdg_options_file_path
201
+ if path && File.exist?(path)
202
+ path
203
+ end
204
+ end
205
+
206
+ def home_options_file_path
187
207
  File.join(File.expand_path("~"), ".rspec")
188
208
  rescue ArgumentError
189
209
  # :nocov:
@@ -191,6 +211,23 @@ module RSpec
191
211
  nil
192
212
  # :nocov:
193
213
  end
214
+
215
+ def xdg_options_file_path
216
+ xdg_config_home = resolve_xdg_config_home
217
+ if xdg_config_home
218
+ File.join(xdg_config_home, "rspec", "options")
219
+ end
220
+ end
221
+
222
+ def resolve_xdg_config_home
223
+ File.expand_path(ENV.fetch("XDG_CONFIG_HOME", "~/.config"))
224
+ rescue ArgumentError
225
+ # :nocov:
226
+ # On Ruby 2.4, `File.expand("~")` works even if `ENV['HOME']` is not set.
227
+ # But on earlier versions, it fails.
228
+ nil
229
+ # :nocov:
230
+ end
194
231
  end
195
232
  end
196
233
  end
@@ -393,7 +393,7 @@ module RSpec
393
393
  end
394
394
  end
395
395
 
396
- # rubocop:disable Style/AccessorMethodName
396
+ # rubocop:disable Naming/AccessorMethodName
397
397
 
398
398
  # @private
399
399
  #
@@ -420,7 +420,7 @@ module RSpec
420
420
  self.display_exception = exception
421
421
  end
422
422
 
423
- # rubocop:enable Style/AccessorMethodName
423
+ # rubocop:enable Naming/AccessorMethodName
424
424
 
425
425
  # @private
426
426
  #
@@ -642,12 +642,12 @@ module RSpec
642
642
  @reporter = reporter
643
643
  end
644
644
 
645
- # rubocop:disable Style/AccessorMethodName
645
+ # rubocop:disable Naming/AccessorMethodName
646
646
  def set_exception(exception)
647
647
  reporter.notify_non_example_exception(exception, "An error occurred in #{description}.")
648
648
  RSpec.world.wants_to_quit = true
649
649
  end
650
- # rubocop:enable Style/AccessorMethodName
650
+ # rubocop:enable Naming/AccessorMethodName
651
651
  end
652
652
  end
653
653
  end
@@ -107,6 +107,7 @@ module RSpec
107
107
  # @private
108
108
  # @macro [attach] define_example_method
109
109
  # @!scope class
110
+ # @method $1
110
111
  # @overload $1
111
112
  # @overload $1(&example_implementation)
112
113
  # @param example_implementation [Block] The implementation of the example.
@@ -0,0 +1,45 @@
1
+ RSpec::Support.require_rspec_core "bisect/utilities"
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+ # Contains common logic for formatters used by `--bisect` to communicate results
7
+ # back to the bisect runner.
8
+ #
9
+ # Subclasses must define a `notify_results(all_example_ids, failed_example_ids)`
10
+ # method.
11
+ # @private
12
+ class BaseBisectFormatter
13
+ def self.inherited(formatter)
14
+ Formatters.register formatter, :start_dump, :example_failed, :example_finished
15
+ end
16
+
17
+ def initialize(expected_failures)
18
+ @all_example_ids = []
19
+ @failed_example_ids = []
20
+ @remaining_failures = expected_failures
21
+ end
22
+
23
+ def example_failed(notification)
24
+ @failed_example_ids << notification.example.id
25
+ end
26
+
27
+ def example_finished(notification)
28
+ @all_example_ids << notification.example.id
29
+ return unless @remaining_failures.include?(notification.example.id)
30
+ @remaining_failures.delete(notification.example.id)
31
+
32
+ status = notification.example.execution_result.status
33
+ return if status == :failed && !@remaining_failures.empty?
34
+ RSpec.world.wants_to_quit = true
35
+ end
36
+
37
+ def start_dump(_notification)
38
+ # `notify_results` is defined in the subclass
39
+ notify_results(Bisect::ExampleSetDescriptor.new(
40
+ @all_example_ids, @failed_example_ids))
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end