rspec-core 3.9.3 → 3.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30e931022769b69911776a8c64de53481785df0074e84693b5e4031c20a53bb2
4
- data.tar.gz: 9d5f23168383bff0e8f3152d9e111ed7600ee1cefb9ccaeb6c1a0fa384dfe3b1
3
+ metadata.gz: c9793ccaf293fdd1820e28574b1b6db9999ee75618d8abfe3238d3bcaaffcd95
4
+ data.tar.gz: 767dee6f32f9d5c84df489e7a92ecc13ccf0b5becee1ce350b9250e1c994a763
5
5
  SHA512:
6
- metadata.gz: 50a9d24a978ca5c0e13bccb4b10343aeac24d2895692d0a2c7d3a6ab429213ede9b9406d4deca6d7cb496f91919eb38fe711ca0294eb94d26e60e4c07abb2e4b
7
- data.tar.gz: e412bad1efb696f88065ba2adab372ef8e613ece6f70dd8bf193daeab5e3c8ea41978d3d2b3f5829c4a11c3eb3e2f01428f979d8b75f1f658dc4dcb78fdbf263
6
+ metadata.gz: 88fbe10e6f8e2ce1a4ba1c3e72283990e4dbf4dbf897067e297f7b3084e42f65e752c8c4381761b630ebef42c204e897208392b1421163eb645351d511249750
7
+ data.tar.gz: 6759b7780dfe8b1e5fedf1d55f864acda4d9ad635013e885ae2457c4c1c37ea28ed3d141e358966da290c3ff4a7de50da8e794933778a393e383c25cbcd95d82
checksums.yaml.gz.sig CHANGED
Binary file
data/Changelog.md CHANGED
@@ -1,4 +1,51 @@
1
- # 3.9.3 / 2020-09-30
1
+ ### Development
2
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.11.0...3-11-maintenance)
3
+
4
+ ### 3.11.0 / 2022-02-09
5
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.10.2...v3.11.0)
6
+
7
+ Enhancements:
8
+
9
+ * Improve pluralisation of words ending with `s` (like process). (Joshua Pinter, #2779)
10
+ * Add ordering by file modification time (most recent first). (Matheus Richard, #2778)
11
+ * Add `to_s` to reserved names for #let and #subject. (Nick Flückiger, #2886)
12
+ * Introduce `RSpec.current_scope` to expose the current scope in which
13
+ RSpec is executing. e.g. `:before_example_hook`, `:example` etc. (@odinhb, #2895)
14
+ * Add named bold colours as options for custom colours. (#2913, #2914)
15
+ * Warn when (but not prevent) a `SystemExit` occurs. (Jared Beck, #2926)
16
+
17
+ ### 3.10.2 / 2022-01-27
18
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.10.1...v3.10.2)
19
+
20
+ Bug fixes:
21
+
22
+ * Ensure bisect communication uses consistent encoding. (Mike Jarema, #2852)
23
+ * Fix exception presenter when the root cause exception has nil backtrace.
24
+ (Zinovyev Ivan, #2903)
25
+ * Fix `inspect` output of `RSpec::Core::Example::Procsy` to namespace correctly.
26
+ (Keiko Kaneko, #2915)
27
+ * Ensure formatters not exposing `#output` will not crash duplicate check.
28
+ (@niceking, #2916)
29
+
30
+ ### 3.10.1 / 2020-12-27
31
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.10.0...v3.10.1)
32
+
33
+ Bug fixes:
34
+
35
+ * RSpec warning output was missing deprecations from Ruby, these are now included.
36
+ (Jon Rowe, #2811)
37
+
38
+ ### 3.10.0 / 2020-10-30
39
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.9.3...v3.10.0)
40
+
41
+ Enhancements:
42
+
43
+ * Memoize `RSpec::Core::Formatters::ExceptionPresenter#exception_lines` to improve performance
44
+ with slow exception messages. (Maxime Lapointe, #2743)
45
+ * Add configuration for an error exit code (to disambiguate errored builds from failed builds
46
+ by exit status). (Dana Sherson, #2749)
47
+
48
+ ### 3.9.3 / 2020-09-30
2
49
  [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.9.2...v3.9.3)
3
50
 
4
51
  Bug Fixes:
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # rspec-core [![Build Status](https://secure.travis-ci.org/rspec/rspec-core.svg?branch=main)](http://travis-ci.org/rspec/rspec-core) [![Code Climate](https://codeclimate.com/github/rspec/rspec-core.svg)](https://codeclimate.com/github/rspec/rspec-core)
1
+ # rspec-core [![Build Status](https://github.com/rspec/rspec-core/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-core/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-core.svg)](https://codeclimate.com/github/rspec/rspec-core)
2
2
 
3
3
  rspec-core provides the structure for writing executable examples of how your
4
4
  code should behave, and an `rspec` command with tools to constrain which
@@ -29,11 +29,22 @@ module RSpec
29
29
  end
30
30
 
31
31
  # Wraps a pipe to support sending objects between a child and
32
- # parent process.
32
+ # parent process. Where supported, encoding is explicitly
33
+ # set to ensure binary data is able to pass from child to
34
+ # parent.
33
35
  # @private
34
36
  class Channel
37
+ if String.method_defined?(:encoding)
38
+ MARSHAL_DUMP_ENCODING = Marshal.dump("").encoding
39
+ end
40
+
35
41
  def initialize
36
42
  @read_io, @write_io = IO.pipe
43
+
44
+ if defined?(MARSHAL_DUMP_ENCODING) && IO.method_defined?(:set_encoding)
45
+ # Ensure the pipe can send any content produced by Marshal.dump
46
+ @write_io.set_encoding MARSHAL_DUMP_ENCODING
47
+ end
37
48
  end
38
49
 
39
50
  def send(message)
@@ -242,6 +242,11 @@ module RSpec
242
242
  # @return [Integer]
243
243
  add_setting :failure_exit_code
244
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
+
245
250
  # @macro add_setting
246
251
  # Whether or not to fail when there are no RSpec examples (default: false).
247
252
  # @return [Boolean]
@@ -523,6 +528,7 @@ module RSpec
523
528
  @pattern = '**{,/*/**}/*_spec.rb'
524
529
  @exclude_pattern = ''
525
530
  @failure_exit_code = 1
531
+ @error_exit_code = nil # so it can be overridden by failure exit code
526
532
  @fail_if_no_examples = false
527
533
  @spec_files_loaded = false
528
534
 
@@ -2057,10 +2063,13 @@ module RSpec
2057
2063
  return yield if dry_run?
2058
2064
 
2059
2065
  begin
2066
+ RSpec.current_scope = :before_suite_hook
2060
2067
  run_suite_hooks("a `before(:suite)` hook", @before_suite_hooks)
2061
2068
  yield
2062
2069
  ensure
2070
+ RSpec.current_scope = :after_suite_hook
2063
2071
  run_suite_hooks("an `after(:suite)` hook", @after_suite_hooks)
2072
+ RSpec.current_scope = :suite
2064
2073
  end
2065
2074
  end
2066
2075
 
@@ -2113,6 +2122,14 @@ module RSpec
2113
2122
  relative_file = Metadata.relative_path(file)
2114
2123
  reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.")
2115
2124
  RSpec.world.wants_to_quit = true
2125
+ rescue SystemExit => ex
2126
+ relative_file = Metadata.relative_path(file)
2127
+ reporter.notify_non_example_exception(
2128
+ ex,
2129
+ "While loading #{relative_file} an `exit` / `raise SystemExit` occurred, RSpec will now quit."
2130
+ )
2131
+ RSpec.world.rspec_is_quitting = true
2132
+ raise ex
2116
2133
  end
2117
2134
 
2118
2135
  def handle_suite_hook(scope, meta)
@@ -51,6 +51,7 @@ module RSpec
51
51
  argv << "--order" << @submitted_options[:order] if @submitted_options[:order]
52
52
 
53
53
  add_failure_exit_code(argv)
54
+ add_error_exit_code(argv)
54
55
  add_full_description(argv)
55
56
  add_filter(argv, :inclusion, @filter_manager.inclusions)
56
57
  add_filter(argv, :exclusion, @filter_manager.exclusions)
@@ -67,6 +68,12 @@ module RSpec
67
68
  argv << "--failure-exit-code" << @submitted_options[:failure_exit_code].to_s
68
69
  end
69
70
 
71
+ def add_error_exit_code(argv)
72
+ return unless @submitted_options[:error_exit_code]
73
+
74
+ argv << "--error-exit-code" << @submitted_options[:error_exit_code].to_s
75
+ end
76
+
70
77
  def add_full_description(argv)
71
78
  return unless @submitted_options[:full_description]
72
79
 
@@ -259,6 +259,7 @@ module RSpec
259
259
  with_around_and_singleton_context_hooks do
260
260
  begin
261
261
  run_before_example
262
+ RSpec.current_scope = :example
262
263
  @example_group_instance.instance_exec(self, &@example_block)
263
264
 
264
265
  if pending?
@@ -278,6 +279,7 @@ module RSpec
278
279
  rescue AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt => e
279
280
  set_exception(e)
280
281
  ensure
282
+ RSpec.current_scope = :after_example_hook
281
283
  run_after_example
282
284
  end
283
285
  end
@@ -375,7 +377,7 @@ module RSpec
375
377
 
376
378
  # @private
377
379
  def inspect
378
- @example.inspect.gsub('Example', 'ExampleProcsy')
380
+ @example.inspect.gsub('Example', 'Example::Procsy')
379
381
  end
380
382
  end
381
383
 
@@ -462,6 +464,7 @@ module RSpec
462
464
  end
463
465
 
464
466
  def with_around_example_hooks
467
+ RSpec.current_scope = :before_example_hook
465
468
  hooks.run(:around, :example, self) { yield }
466
469
  rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
467
470
  set_exception(e)
@@ -602,6 +602,7 @@ module RSpec
602
602
 
603
603
  should_run_context_hooks = descendant_filtered_examples.any?
604
604
  begin
605
+ RSpec.current_scope = :before_context_hook
605
606
  run_before_context_hooks(new('before(:context) hook')) if should_run_context_hooks
606
607
  result_for_this_group = run_examples(reporter)
607
608
  results_for_descendants = ordering_strategy.order(children).map { |child| child.run(reporter) }.all?
@@ -614,6 +615,7 @@ module RSpec
614
615
  RSpec.world.wants_to_quit = true if reporter.fail_fast_limit_met?
615
616
  false
616
617
  ensure
618
+ RSpec.current_scope = :after_context_hook
617
619
  run_after_context_hooks(new('after(:context) hook')) if should_run_context_hooks
618
620
  reporter.example_group_finished(self)
619
621
  end
@@ -701,6 +703,7 @@ module RSpec
701
703
  end
702
704
  end
703
705
 
706
+ # @private
704
707
  def initialize(inspect_output=nil)
705
708
  @__inspect_output = inspect_output || '(no description provided)'
706
709
  super() # no args get passed
@@ -782,6 +785,7 @@ module RSpec
782
785
  # @return [String] the location where the shared example was included
783
786
  attr_reader :inclusion_location
784
787
 
788
+ # @private
785
789
  def initialize(shared_group_name, inclusion_location)
786
790
  @shared_group_name = shared_group_name
787
791
  @inclusion_location = inclusion_location
@@ -7,15 +7,23 @@ module RSpec
7
7
  # @private
8
8
  VT100_CODES =
9
9
  {
10
- :black => 30,
11
- :red => 31,
12
- :green => 32,
13
- :yellow => 33,
14
- :blue => 34,
15
- :magenta => 35,
16
- :cyan => 36,
17
- :white => 37,
18
- :bold => 1,
10
+ :black => 30,
11
+ :red => 31,
12
+ :green => 32,
13
+ :yellow => 33,
14
+ :blue => 34,
15
+ :magenta => 35,
16
+ :cyan => 36,
17
+ :white => 37,
18
+ :bold_black => '1;30',
19
+ :bold_red => '1;31',
20
+ :bold_green => '1;32',
21
+ :bold_yellow => '1;33',
22
+ :bold_blue => '1;34',
23
+ :bold_magenta => '1;35',
24
+ :bold_cyan => '1;36',
25
+ :bold_white => '1;37',
26
+ :bold => 1,
19
27
  }
20
28
  # @private
21
29
  VT100_CODE_VALUES = VT100_CODES.invert
@@ -55,7 +55,7 @@ module RSpec
55
55
  cause << " #{line}"
56
56
  end
57
57
 
58
- unless last_cause.backtrace.empty?
58
+ unless last_cause.backtrace.nil? || last_cause.backtrace.empty?
59
59
  cause << (" #{backtrace_formatter.format_backtrace(last_cause.backtrace, example.metadata).first}")
60
60
  end
61
61
  end
@@ -183,12 +183,14 @@ module RSpec
183
183
  # rubocop:enable Lint/RescueException
184
184
 
185
185
  def exception_lines
186
- lines = []
187
- lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
188
- encoded_string(exception_message_string(exception)).split("\n").each do |line|
189
- lines << (line.empty? ? line : " #{line}")
186
+ @exception_lines ||= begin
187
+ lines = []
188
+ lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
189
+ encoded_string(exception_message_string(exception)).split("\n").each do |line|
190
+ lines << (line.empty? ? line : " #{line}")
191
+ end
192
+ lines
190
193
  end
191
- lines
192
194
  end
193
195
 
194
196
  def extra_failure_lines
@@ -86,7 +86,15 @@ module RSpec
86
86
  # @param string [String] word to be pluralized
87
87
  # @return [String] pluralized word
88
88
  def self.pluralize(count, string)
89
- "#{count} #{string}#{'s' unless count.to_f == 1}"
89
+ pluralized_string = if count.to_f == 1
90
+ string
91
+ elsif string.end_with?('s') # e.g. "process"
92
+ "#{string}es" # e.g. "processes"
93
+ else
94
+ "#{string}s"
95
+ end
96
+
97
+ "#{count} #{pluralized_string}"
90
98
  end
91
99
 
92
100
  # @api private
@@ -79,7 +79,7 @@ module RSpec::Core::Formatters
79
79
 
80
80
  # Register the formatter class
81
81
  # @param formatter_class [Class] formatter class to register
82
- # @param notifications [Symbol, ...] one or more notifications to be
82
+ # @param notifications [Array<Symbol>] one or more notifications to be
83
83
  # registered to the specified formatter
84
84
  #
85
85
  # @see RSpec::Core::Formatters::BaseFormatter
@@ -194,10 +194,16 @@ module RSpec::Core::Formatters
194
194
 
195
195
  def duplicate_formatter_exists?(new_formatter)
196
196
  @formatters.any? do |formatter|
197
- formatter.class == new_formatter.class && formatter.output == new_formatter.output
197
+ formatter.class == new_formatter.class &&
198
+ has_matching_output?(formatter, new_formatter)
198
199
  end
199
200
  end
200
201
 
202
+ def has_matching_output?(formatter, new_formatter)
203
+ return true unless formatter.respond_to?(:output) && new_formatter.respond_to?(:output)
204
+ formatter.output == new_formatter.output
205
+ end
206
+
201
207
  def existing_formatter_implements?(notification)
202
208
  @reporter.registered_listeners(notification).any?
203
209
  end
@@ -37,7 +37,7 @@ module RSpec
37
37
  runner, options.args, formatter
38
38
  )
39
39
 
40
- success ? 0 : runner.configuration.failure_exit_code
40
+ runner.exit_code(success)
41
41
  end
42
42
 
43
43
  private
@@ -78,6 +78,7 @@ module RSpec
78
78
  # @note If you are using RSpec's newer expect-based syntax you may
79
79
  # want to use `is_expected.to` instead of `should`.
80
80
  def should(matcher=nil, message=nil)
81
+ enforce_value_expectation(matcher, 'should')
81
82
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(subject, matcher, message)
82
83
  end
83
84
 
@@ -97,6 +98,7 @@ module RSpec
97
98
  # @note If you are using RSpec's newer expect-based syntax you may
98
99
  # want to use `is_expected.to_not` instead of `should_not`.
99
100
  def should_not(matcher=nil, message=nil)
101
+ enforce_value_expectation(matcher, 'should_not')
100
102
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(subject, matcher, message)
101
103
  end
102
104
 
@@ -144,6 +146,26 @@ module RSpec
144
146
  end
145
147
  end
146
148
 
149
+ # @private
150
+ def enforce_value_expectation(matcher, method_name)
151
+ return if matcher_supports_value_expectations?(matcher)
152
+
153
+ RSpec.deprecate(
154
+ "#{method_name} #{RSpec::Support::ObjectFormatter.format(matcher)}",
155
+ :message =>
156
+ "The implicit block expectation syntax is deprecated, you should pass " \
157
+ "a block to `expect` to use the provided block expectation matcher " \
158
+ "(#{RSpec::Support::ObjectFormatter.format(matcher)}), " \
159
+ "or the matcher must implement `supports_value_expectations?`."
160
+ )
161
+ end
162
+
163
+ def matcher_supports_value_expectations?(matcher)
164
+ matcher.supports_value_expectations?
165
+ rescue
166
+ true
167
+ end
168
+
147
169
  # @private
148
170
  class ThreadsafeMemoized
149
171
  def initialize
@@ -285,9 +307,13 @@ EOS
285
307
  # We have to pass the block directly to `define_method` to
286
308
  # allow it to use method constructs like `super` and `return`.
287
309
  raise "#let or #subject called without a block" if block.nil?
288
- raise(
289
- "#let or #subject called with a reserved name #initialize"
290
- ) if :initialize == name
310
+
311
+ # A list of reserved words that can't be used as a name for a memoized helper
312
+ # Matches for both symbols and passed strings
313
+ if [:initialize, :to_s].include?(name.to_sym)
314
+ raise ArgumentError, "#let or #subject called with reserved name `#{name}`"
315
+ end
316
+
291
317
  our_module = MemoizedHelpers.module_for(self)
292
318
 
293
319
  # If we have a module clash in our helper module
@@ -58,10 +58,11 @@ module RSpec::Core
58
58
  end
59
59
 
60
60
  parser.on('--order TYPE[:SEED]', 'Run examples by the specified order type.',
61
- ' [defined] examples and groups are run in the order they are defined',
62
- ' [rand] randomize the order of groups and examples',
63
- ' [random] alias for rand',
64
- ' [random:SEED] e.g. --order random:123') do |o|
61
+ ' [defined] examples and groups are run in the order they are defined',
62
+ ' [rand] randomize the order of groups and examples',
63
+ ' [random] alias for rand',
64
+ ' [random:SEED] e.g. --order random:123',
65
+ ' [recently-modified] run the most recently modified files first') do |o|
65
66
  options[:order] = o
66
67
  end
67
68
 
@@ -95,6 +96,11 @@ module RSpec::Core
95
96
  options[:failure_exit_code] = code
96
97
  end
97
98
 
99
+ parser.on('--error-exit-code CODE', Integer,
100
+ 'Override the exit code used when there are errors loading or running specs outside of examples.') do |code|
101
+ options[:error_exit_code] = code
102
+ end
103
+
98
104
  parser.on('-X', '--[no-]drb', 'Run examples via DRb.') do |use_drb|
99
105
  options[:drb] = use_drb
100
106
  options[:runner] = RSpec::Core::Invocations::DRbWithFallback.new if use_drb
@@ -179,6 +185,9 @@ module RSpec::Core
179
185
  end
180
186
 
181
187
  parser.on('-w', '--warnings', 'Enable ruby warnings') do
188
+ if Object.const_defined?(:Warning) && Warning.respond_to?(:[]=)
189
+ Warning[:deprecated] = true
190
+ end
182
191
  $VERBOSE = true
183
192
  end
184
193
 
@@ -58,6 +58,14 @@ module RSpec
58
58
  MAX_32_BIT = 4_294_967_295
59
59
  end
60
60
 
61
+ # @private
62
+ # Orders items by modification time (most recent modified first).
63
+ class RecentlyModified
64
+ def order(list)
65
+ list.sort_by { |item| -File.mtime(item.metadata[:absolute_file_path]).to_i }
66
+ end
67
+ end
68
+
61
69
  # @private
62
70
  # Orders items based on a custom block.
63
71
  class Custom
@@ -77,7 +85,8 @@ module RSpec
77
85
  @configuration = configuration
78
86
  @strategies = {}
79
87
 
80
- register(:random, Random.new(configuration))
88
+ register(:random, Random.new(configuration))
89
+ register(:recently_modified, RecentlyModified.new)
81
90
 
82
91
  identity = Identity.new
83
92
  register(:defined, identity)
@@ -132,6 +141,8 @@ module RSpec
132
141
  :random
133
142
  elsif order == 'defined'
134
143
  :defined
144
+ elsif order == 'recently-modified'
145
+ :recently_modified
135
146
  end
136
147
 
137
148
  register_ordering(:global, ordering_registry.fetch(ordering_name)) if ordering_name
@@ -38,7 +38,7 @@ module RSpec
38
38
  # @param message [String] optional message to add to the summary report.
39
39
  #
40
40
  # @example
41
- # describe "an example" do
41
+ # describe "some behaviour" do
42
42
  # # reported as "Pending: no reason given"
43
43
  # it "is pending with no message" do
44
44
  # pending
@@ -52,21 +52,13 @@ module RSpec
52
52
  # end
53
53
  # end
54
54
  #
55
- # @note `before(:example)` hooks are eval'd when you use the `pending`
56
- # method within an example. If you want to declare an example `pending`
57
- # and bypass the `before` hooks as well, you can pass `:pending => true`
58
- # to the `it` method:
59
- #
60
- # it "does something", :pending => true do
61
- # # ...
62
- # end
63
- #
64
- # or pass `:pending => "something else getting finished"` to add a
65
- # message to the summary report:
66
- #
67
- # it "does something", :pending => "something else getting finished" do
68
- # # ...
69
- # end
55
+ # @note When using `pending` inside an example body using this method
56
+ # hooks, such as `before(:example)`, have already be run. This means that
57
+ # a failure from the code in the `before` hook will prevent the example
58
+ # from being considered pending, as the example body would not be
59
+ # executed. If you need to consider hooks as pending as well you can use
60
+ # the pending metadata as an alternative, e.g.
61
+ # `it "does something", pending: "message"`.
70
62
  def pending(message=nil)
71
63
  current_example = RSpec.current_example
72
64
 
@@ -12,7 +12,7 @@
12
12
  # the additional setup, and require it from the spec files that actually need
13
13
  # it.
14
14
  #
15
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
15
+ # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
16
  RSpec.configure do |config|
17
17
  # rspec-expectations config goes here. You can use an alternate
18
18
  # assertion/expectation library such as wrong or the stdlib/minitest
@@ -61,9 +61,7 @@ RSpec.configure do |config|
61
61
 
62
62
  # Limits the available syntax to the non-monkey patched syntax that is
63
63
  # recommended. For more details, see:
64
- # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
65
- # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
66
- # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
64
+ # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode
67
65
  config.disable_monkey_patching!
68
66
 
69
67
  # This setting enables warnings. It's recommended, but in some cases may
@@ -84,7 +84,7 @@ module RSpec
84
84
  # @param out [IO] output stream
85
85
  def run(err, out)
86
86
  setup(err, out)
87
- return @configuration.reporter.exit_early(@configuration.failure_exit_code) if RSpec.world.wants_to_quit
87
+ return @configuration.reporter.exit_early(exit_code) if RSpec.world.wants_to_quit
88
88
 
89
89
  run_specs(@world.ordered_example_groups).tap do
90
90
  persist_example_statuses
@@ -112,7 +112,7 @@ module RSpec
112
112
  # failed.
113
113
  def run_specs(example_groups)
114
114
  examples_count = @world.example_count(example_groups)
115
- success = @configuration.reporter.report(examples_count) do |reporter|
115
+ examples_passed = @configuration.reporter.report(examples_count) do |reporter|
116
116
  @configuration.with_suite_hooks do
117
117
  if examples_count == 0 && @configuration.fail_if_no_examples
118
118
  return @configuration.failure_exit_code
@@ -120,9 +120,9 @@ module RSpec
120
120
 
121
121
  example_groups.map { |g| g.run(reporter) }.all?
122
122
  end
123
- end && !@world.non_example_failure
123
+ end
124
124
 
125
- success ? 0 : @configuration.failure_exit_code
125
+ exit_code(examples_passed)
126
126
  end
127
127
 
128
128
  # @private
@@ -186,6 +186,14 @@ module RSpec
186
186
  end
187
187
  end
188
188
 
189
+ # @private
190
+ def exit_code(examples_passed=false)
191
+ return @configuration.error_exit_code || @configuration.failure_exit_code if @world.non_example_failure
192
+ return @configuration.failure_exit_code unless examples_passed
193
+
194
+ 0
195
+ end
196
+
189
197
  private
190
198
 
191
199
  def persist_example_statuses
@@ -3,7 +3,7 @@ module RSpec
3
3
  # Version information for RSpec Core.
4
4
  module Version
5
5
  # Current version of RSpec Core, in semantic versioning format.
6
- STRING = '3.9.3'
6
+ STRING = '3.11.0'
7
7
  end
8
8
  end
9
9
  end
@@ -10,6 +10,13 @@ module RSpec
10
10
  # Used internally to determine what to do when a SIGINT is received.
11
11
  attr_accessor :wants_to_quit
12
12
 
13
+ # Used internally to signify that a SystemExit occurred in
14
+ # `Configuration#load_file_handling_errors`, and thus examples cannot
15
+ # be counted accurately. Specifically, we cannot accurately report
16
+ # "No examples found".
17
+ # @private
18
+ attr_accessor :rspec_is_quitting
19
+
13
20
  # Used internally to signal that a failure outside of an example
14
21
  # has occurred, and that therefore the exit status should indicate
15
22
  # the run failed.
@@ -18,6 +25,7 @@ module RSpec
18
25
 
19
26
  def initialize(configuration=RSpec.configuration)
20
27
  @wants_to_quit = false
28
+ @rspec_is_quitting = false
21
29
  @configuration = configuration
22
30
  configuration.world = self
23
31
  @example_groups = []
@@ -184,10 +192,12 @@ module RSpec
184
192
  return unless example_count.zero?
185
193
 
186
194
  example_groups.clear
187
- if filter_manager.empty?
188
- report_filter_message("No examples found.")
189
- elsif exclusion_filter.empty? || inclusion_filter.empty?
190
- report_filter_message(everything_filtered_message)
195
+ unless rspec_is_quitting
196
+ if filter_manager.empty?
197
+ report_filter_message("No examples found.")
198
+ elsif exclusion_filter.empty? || inclusion_filter.empty?
199
+ report_filter_message(everything_filtered_message)
200
+ end
191
201
  end
192
202
  end
193
203
 
data/lib/rspec/core.rb CHANGED
@@ -129,6 +129,32 @@ module RSpec
129
129
  RSpec::Support.thread_local_data[:current_example] = example
130
130
  end
131
131
 
132
+ # Set the current scope rspec is executing in
133
+ # @api private
134
+ def self.current_scope=(scope)
135
+ RSpec::Support.thread_local_data[:current_scope] = scope
136
+ end
137
+ RSpec.current_scope = :suite
138
+
139
+ # Get the current RSpec execution scope
140
+ #
141
+ # Returns (in order of lifecycle):
142
+ # * `:suite` as an initial value, this is outside of the test lifecycle.
143
+ # * `:before_suite_hook` during `before(:suite)` hooks.
144
+ # * `:before_context_hook` during `before(:context)` hooks.
145
+ # * `:before_example_hook` during `before(:example)` hooks and `around(:example)` before `example.run`.
146
+ # * `:example` within the example run.
147
+ # * `:after_example_hook` during `after(:example)` hooks and `around(:example)` after `example.run`.
148
+ # * `:after_context_hook` during `after(:context)` hooks.
149
+ # * `:after_suite_hook` during `after(:suite)` hooks.
150
+ # * `:suite` as a final value, again this is outside of the test lifecycle.
151
+ #
152
+ # Reminder, `:context` hooks have `:all` alias and `:example` hooks have `:each` alias.
153
+ # @return [Symbol]
154
+ def self.current_scope
155
+ RSpec::Support.thread_local_data[:current_scope]
156
+ end
157
+
132
158
  # @private
133
159
  # Internal container for global non-configuration data.
134
160
  def self.world
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.3
4
+ version: 3.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Baker
@@ -46,7 +46,7 @@ cert_chain:
46
46
  ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
47
47
  F3MdtaDehhjC
48
48
  -----END CERTIFICATE-----
49
- date: 2020-09-30 00:00:00.000000000 Z
49
+ date: 2022-02-09 00:00:00.000000000 Z
50
50
  dependencies:
51
51
  - !ruby/object:Gem::Dependency
52
52
  name: rspec-support
@@ -54,14 +54,14 @@ dependencies:
54
54
  requirements:
55
55
  - - "~>"
56
56
  - !ruby/object:Gem::Version
57
- version: 3.9.3
57
+ version: 3.11.0
58
58
  type: :runtime
59
59
  prerelease: false
60
60
  version_requirements: !ruby/object:Gem::Requirement
61
61
  requirements:
62
62
  - - "~>"
63
63
  - !ruby/object:Gem::Version
64
- version: 3.9.3
64
+ version: 3.11.0
65
65
  - !ruby/object:Gem::Dependency
66
66
  name: cucumber
67
67
  requirement: !ruby/object:Gem::Requirement
@@ -267,7 +267,7 @@ licenses:
267
267
  - MIT
268
268
  metadata:
269
269
  bug_tracker_uri: https://github.com/rspec/rspec-core/issues
270
- changelog_uri: https://github.com/rspec/rspec-core/blob/v3.9.3/Changelog.md
270
+ changelog_uri: https://github.com/rspec/rspec-core/blob/v3.11.0/Changelog.md
271
271
  documentation_uri: https://rspec.info/documentation/
272
272
  mailing_list_uri: https://groups.google.com/forum/#!forum/rspec
273
273
  source_code_uri: https://github.com/rspec/rspec-core
@@ -287,8 +287,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
287
  - !ruby/object:Gem::Version
288
288
  version: '0'
289
289
  requirements: []
290
- rubygems_version: 3.1.3
290
+ rubygems_version: 3.3.3
291
291
  signing_key:
292
292
  specification_version: 4
293
- summary: rspec-core-3.9.3
293
+ summary: rspec-core-3.11.0
294
294
  test_files: []
metadata.gz.sig CHANGED
Binary file