rspec-core 3.8.2 → 3.10.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.
@@ -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
 
@@ -231,8 +231,13 @@ module RSpec
231
231
  @example_group_class
232
232
  end
233
233
 
234
- alias_method :pending?, :pending
235
- alias_method :skipped?, :skip
234
+ def pending?
235
+ !!pending
236
+ end
237
+
238
+ def skipped?
239
+ !!skip
240
+ end
236
241
 
237
242
  # @api private
238
243
  # instance_execs the block passed to the constructor in the context of
@@ -577,7 +582,9 @@ module RSpec
577
582
  # this indicates whether or not it now passes.
578
583
  attr_accessor :pending_fixed
579
584
 
580
- alias pending_fixed? pending_fixed
585
+ def pending_fixed?
586
+ !!pending_fixed
587
+ end
581
588
 
582
589
  # @return [Boolean] Indicates if the example was completely skipped
583
590
  # (typically done via `:skip` metadata or the `skip` method). Skipped examples
@@ -7,7 +7,7 @@ module RSpec
7
7
  # ExampleGroup and {Example} are the main structural elements of
8
8
  # rspec-core. Consider this example:
9
9
  #
10
- # describe Thing do
10
+ # RSpec.describe Thing do
11
11
  # it "does something" do
12
12
  # end
13
13
  # end
@@ -90,7 +90,7 @@ module RSpec
90
90
  # Returns the class or module passed to the `describe` method (or alias).
91
91
  # Returns nil if the subject is not a class or module.
92
92
  # @example
93
- # describe Thing do
93
+ # RSpec.describe Thing do
94
94
  # it "does something" do
95
95
  # described_class == Thing
96
96
  # end
@@ -111,16 +111,14 @@ module RSpec
111
111
  # @overload $1
112
112
  # @overload $1(&example_implementation)
113
113
  # @param example_implementation [Block] The implementation of the example.
114
- # @overload $1(doc_string, *metadata_keys, metadata={})
114
+ # @overload $1(doc_string, *metadata)
115
115
  # @param doc_string [String] The example's doc string.
116
- # @param metadata [Hash] Metadata for the example.
117
- # @param metadata_keys [Array<Symbol>] Metadata tags for the example.
118
- # Will be transformed into hash entries with `true` values.
119
- # @overload $1(doc_string, *metadata_keys, metadata={}, &example_implementation)
116
+ # @param metadata [Array<Symbol>, Hash] Metadata for the example.
117
+ # Symbols will be transformed into hash entries with `true` values.
118
+ # @overload $1(doc_string, *metadata, &example_implementation)
120
119
  # @param doc_string [String] The example's doc string.
121
- # @param metadata [Hash] Metadata for the example.
122
- # @param metadata_keys [Array<Symbol>] Metadata tags for the example.
123
- # Will be transformed into hash entries with `true` values.
120
+ # @param metadata [Array<Symbol>, Hash] Metadata for the example.
121
+ # Symbols will be transformed into hash entries with `true` values.
124
122
  # @param example_implementation [Block] The implementation of the example.
125
123
  # @yield [Example] the example object
126
124
  # @example
@@ -139,6 +137,11 @@ module RSpec
139
137
  # $1 "does something" do |ex|
140
138
  # # ex is the Example object that contains metadata about the example
141
139
  # end
140
+ #
141
+ # @example
142
+ # $1 "does something", :slow, :load_factor => 100 do
143
+ # end
144
+ #
142
145
  def self.define_example_method(name, extra_options={})
143
146
  idempotently_define_singleton_method(name) do |*all_args, &block|
144
147
  desc, *args = *all_args
@@ -204,11 +207,10 @@ module RSpec
204
207
  # @overload $1
205
208
  # @overload $1(&example_group_definition)
206
209
  # @param example_group_definition [Block] The definition of the example group.
207
- # @overload $1(doc_string, *metadata_keys, metadata={}, &example_implementation)
210
+ # @overload $1(doc_string, *metadata, &example_implementation)
208
211
  # @param doc_string [String] The group's doc string.
209
- # @param metadata [Hash] Metadata for the group.
210
- # @param metadata_keys [Array<Symbol>] Metadata tags for the group.
211
- # Will be transformed into hash entries with `true` values.
212
+ # @param metadata [Array<Symbol>, Hash] Metadata for the group.
213
+ # Symbols will be transformed into hash entries with `true` values.
212
214
  # @param example_group_definition [Block] The definition of the example group.
213
215
  #
214
216
  # Generates a subclass of this example group which inherits
@@ -223,12 +225,21 @@ module RSpec
223
225
  # do_something_before
224
226
  # end
225
227
  #
228
+ # before(:example, :clean_env) do
229
+ # env.clear!
230
+ # end
231
+ #
226
232
  # let(:thing) { Thing.new }
227
233
  #
228
234
  # $1 "attribute (of something)" do
229
235
  # # examples in the group get the before hook
230
236
  # # declared above, and can access `thing`
231
237
  # end
238
+ #
239
+ # $1 "needs additional setup", :clean_env, :implementation => JSON do
240
+ # # specifies that hooks with matching metadata
241
+ # # should be be run additionally
242
+ # end
232
243
  # end
233
244
  #
234
245
  # @see DSL#describe
@@ -750,8 +761,9 @@ module RSpec
750
761
  "on an example group (e.g. a `describe` or `context` block)."
751
762
  end
752
763
 
753
- super
764
+ super(name, *args)
754
765
  end
766
+ ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
755
767
  end
756
768
  # rubocop:enable Metrics/ClassLength
757
769
 
@@ -113,7 +113,7 @@ module RSpec
113
113
 
114
114
  # @private
115
115
  class FilterRules
116
- PROC_HEX_NUMBER = /0x[0-9a-f]+@/
116
+ PROC_HEX_NUMBER = /0x[0-9a-f]+@?/
117
117
  PROJECT_DIR = File.expand_path('.')
118
118
 
119
119
  attr_accessor :opposite
@@ -1,4 +1,5 @@
1
1
  RSpec::Support.require_rspec_support "directory_maker"
2
+
2
3
  # ## Built-in Formatters
3
4
  #
4
5
  # * progress (default) - Prints dots for passing examples, `F` for failures, `*`
@@ -74,6 +75,7 @@ module RSpec::Core::Formatters
74
75
  autoload :JsonFormatter, 'rspec/core/formatters/json_formatter'
75
76
  autoload :BisectDRbFormatter, 'rspec/core/formatters/bisect_drb_formatter'
76
77
  autoload :ExceptionPresenter, 'rspec/core/formatters/exception_presenter'
78
+ autoload :FailureListFormatter, 'rspec/core/formatters/failure_list_formatter'
77
79
 
78
80
  # Register the formatter class
79
81
  # @param formatter_class [Class] formatter class to register
@@ -212,6 +214,8 @@ module RSpec::Core::Formatters
212
214
  JsonFormatter
213
215
  when 'bisect-drb'
214
216
  BisectDRbFormatter
217
+ when 'f', 'failures'
218
+ FailureListFormatter
215
219
  end
216
220
  end
217
221
 
@@ -6,12 +6,19 @@ module RSpec
6
6
  module Formatters
7
7
  # @private
8
8
  class DocumentationFormatter < BaseTextFormatter
9
- Formatters.register self, :example_group_started, :example_group_finished,
9
+ Formatters.register self, :example_started, :example_group_started, :example_group_finished,
10
10
  :example_passed, :example_pending, :example_failed
11
11
 
12
12
  def initialize(output)
13
13
  super
14
14
  @group_level = 0
15
+
16
+ @example_running = false
17
+ @messages = []
18
+ end
19
+
20
+ def example_started(_notification)
21
+ @example_running = true
15
22
  end
16
23
 
17
24
  def example_group_started(notification)
@@ -27,19 +34,44 @@ module RSpec
27
34
 
28
35
  def example_passed(passed)
29
36
  output.puts passed_output(passed.example)
37
+
38
+ flush_messages
39
+ @example_running = false
30
40
  end
31
41
 
32
42
  def example_pending(pending)
33
43
  output.puts pending_output(pending.example,
34
44
  pending.example.execution_result.pending_message)
45
+
46
+ flush_messages
47
+ @example_running = false
35
48
  end
36
49
 
37
50
  def example_failed(failure)
38
51
  output.puts failure_output(failure.example)
52
+
53
+ flush_messages
54
+ @example_running = false
55
+ end
56
+
57
+ def message(notification)
58
+ if @example_running
59
+ @messages << notification.message
60
+ else
61
+ output.puts "#{current_indentation}#{notification.message}"
62
+ end
39
63
  end
40
64
 
41
65
  private
42
66
 
67
+ def flush_messages
68
+ @messages.each do |message|
69
+ output.puts "#{current_indentation(1)}#{message}"
70
+ end
71
+
72
+ @messages.clear
73
+ end
74
+
43
75
  def passed_output(example)
44
76
  ConsoleCodes.wrap("#{current_indentation}#{example.description.strip}", :success)
45
77
  end
@@ -61,8 +93,8 @@ module RSpec
61
93
  @next_failure_index += 1
62
94
  end
63
95
 
64
- def current_indentation
65
- ' ' * @group_level
96
+ def current_indentation(offset=0)
97
+ ' ' * (@group_level + offset)
66
98
  end
67
99
  end
68
100
  end
@@ -43,7 +43,7 @@ module RSpec
43
43
 
44
44
  if RSpec::Support::RubyFeatures.supports_exception_cause?
45
45
  def formatted_cause(exception)
46
- last_cause = final_exception(exception)
46
+ last_cause = final_exception(exception, [exception])
47
47
  cause = []
48
48
 
49
49
  if exception.cause
@@ -51,11 +51,13 @@ module RSpec
51
51
  cause << '--- Caused by: ---'
52
52
  cause << "#{exception_class_name(last_cause)}:" unless exception_class_name(last_cause) =~ /RSpec/
53
53
 
54
- encoded_string(last_cause.message.to_s).split("\n").each do |line|
54
+ encoded_string(exception_message_string(last_cause)).split("\n").each do |line|
55
55
  cause << " #{line}"
56
56
  end
57
57
 
58
- cause << (" #{backtrace_formatter.format_backtrace(last_cause.backtrace, example.metadata).first}")
58
+ unless last_cause.backtrace.empty?
59
+ cause << (" #{backtrace_formatter.format_backtrace(last_cause.backtrace, example.metadata).first}")
60
+ end
59
61
  end
60
62
 
61
63
  cause
@@ -96,7 +98,8 @@ module RSpec
96
98
 
97
99
  def final_exception(exception, previous=[])
98
100
  cause = exception.cause
99
- if cause && !previous.include?(cause)
101
+
102
+ if cause && Exception === cause && !previous.include?(cause)
100
103
  previous << cause
101
104
  final_exception(cause, previous)
102
105
  else
@@ -171,13 +174,23 @@ module RSpec
171
174
  lines
172
175
  end
173
176
 
177
+ # rubocop:disable Lint/RescueException
178
+ def exception_message_string(exception)
179
+ exception.message.to_s
180
+ rescue Exception => other
181
+ "A #{exception.class} for which `exception.message.to_s` raises #{other.class}."
182
+ end
183
+ # rubocop:enable Lint/RescueException
184
+
174
185
  def exception_lines
175
- lines = []
176
- lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
177
- encoded_string(exception.message.to_s).split("\n").each do |line|
178
- 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
179
193
  end
180
- lines
181
194
  end
182
195
 
183
196
  def extra_failure_lines
@@ -0,0 +1,23 @@
1
+ RSpec::Support.require_rspec_core "formatters/base_formatter"
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+ # @private
7
+ class FailureListFormatter < BaseFormatter
8
+ Formatters.register self, :example_failed, :dump_profile, :message
9
+
10
+ def example_failed(failure)
11
+ output.puts "#{failure.example.location}:#{failure.example.description}"
12
+ end
13
+
14
+ # Discard profile and messages
15
+ #
16
+ # These outputs are not really relevant in the context of this failure
17
+ # list formatter.
18
+ def dump_profile(_profile); end
19
+ def message(_message); end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -13,13 +13,14 @@ module RSpec
13
13
  # @overload before(scope, &block)
14
14
  # @param scope [Symbol] `:example`, `:context`, or `:suite`
15
15
  # (defaults to `:example`)
16
- # @overload before(scope, conditions, &block)
16
+ # @overload before(scope, *conditions, &block)
17
17
  # @param scope [Symbol] `:example`, `:context`, or `:suite`
18
18
  # (defaults to `:example`)
19
- # @param conditions [Hash]
20
- # constrains this hook to examples matching these conditions e.g.
19
+ # @param conditions [Array<Symbol>, Hash] constrains this hook to
20
+ # examples matching these conditions e.g.
21
21
  # `before(:example, :ui => true) { ... }` will only run with examples
22
- # or groups declared with `:ui => true`.
22
+ # or groups declared with `:ui => true`. Symbols will be transformed
23
+ # into hash entries with `true` values.
23
24
  # @overload before(conditions, &block)
24
25
  # @param conditions [Hash]
25
26
  # constrains this hook to examples matching these conditions e.g.
@@ -59,8 +60,10 @@ module RSpec
59
60
  # before(:example) # Declared in a parent group.
60
61
  # before(:example) # Declared in the current group.
61
62
  #
62
- # If more than one `before` is declared within any one scope, they are run
63
- # in the order in which they are declared.
63
+ # If more than one `before` is declared within any one example group, they
64
+ # are run in the order in which they are declared. Any `around` hooks will
65
+ # execute after `before` context hooks but before any `before` example
66
+ # hook regardless of where they are declared.
64
67
  #
65
68
  # ### Conditions
66
69
  #
@@ -74,11 +77,11 @@ module RSpec
74
77
  # end
75
78
  # end
76
79
  #
77
- # describe Something, :authorized => true do
80
+ # RSpec.describe Something, :authorized => true do
78
81
  # # The before hook will run in before each example in this group.
79
82
  # end
80
83
  #
81
- # describe SomethingElse do
84
+ # RSpec.describe SomethingElse do
82
85
  # it "does something", :authorized => true do
83
86
  # # The before hook will run before this example.
84
87
  # end
@@ -159,7 +162,7 @@ module RSpec
159
162
  #
160
163
  # @example before(:example) declared in an {ExampleGroup}
161
164
  #
162
- # describe Thing do
165
+ # RSpec.describe Thing do
163
166
  # before(:example) do
164
167
  # @thing = Thing.new
165
168
  # end
@@ -171,7 +174,7 @@ module RSpec
171
174
  #
172
175
  # @example before(:context) declared in an {ExampleGroup}
173
176
  #
174
- # describe Parser do
177
+ # RSpec.describe Parser do
175
178
  # before(:context) do
176
179
  # File.open(file_to_parse, 'w') do |f|
177
180
  # f.write <<-CONTENT
@@ -213,13 +216,14 @@ module RSpec
213
216
  # @overload after(scope, &block)
214
217
  # @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to
215
218
  # `:example`)
216
- # @overload after(scope, conditions, &block)
219
+ # @overload after(scope, *conditions, &block)
217
220
  # @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to
218
221
  # `:example`)
219
- # @param conditions [Hash]
220
- # constrains this hook to examples matching these conditions e.g.
222
+ # @param conditions [Array<Symbol>, Hash] constrains this hook to
223
+ # examples matching these conditions e.g.
221
224
  # `after(:example, :ui => true) { ... }` will only run with examples
222
- # or groups declared with `:ui => true`.
225
+ # or groups declared with `:ui => true`. Symbols will be transformed
226
+ # into hash entries with `true` values.
223
227
  # @overload after(conditions, &block)
224
228
  # @param conditions [Hash]
225
229
  # constrains this hook to examples matching these conditions e.g.
@@ -260,8 +264,10 @@ module RSpec
260
264
  # after(:suite) # Declared in RSpec.configure.
261
265
  #
262
266
  # This is the reverse of the order in which `before` hooks are run.
263
- # Similarly, if more than one `after` is declared within any one scope,
264
- # they are run in reverse order of that in which they are declared.
267
+ # Similarly, if more than one `after` is declared within any example
268
+ # group, they are run in reverse order of that in which they are declared.
269
+ # Also `around` hooks will run after any `after` example hooks are
270
+ # invoked but before any `after` context hooks.
265
271
  #
266
272
  # @note The `:example` and `:context` scopes are also available as
267
273
  # `:each` and `:all`, respectively. Use whichever you prefer.
@@ -288,13 +294,15 @@ module RSpec
288
294
  # @param scope [Symbol] `:example` (defaults to `:example`)
289
295
  # present for syntax parity with `before` and `after`, but
290
296
  # `:example`/`:each` is the only supported value.
291
- # @overload around(scope, conditions, &block)
297
+ # @overload around(scope, *conditions, &block)
292
298
  # @param scope [Symbol] `:example` (defaults to `:example`)
293
299
  # present for syntax parity with `before` and `after`, but
294
300
  # `:example`/`:each` is the only supported value.
295
- # @param conditions [Hash] constrains this hook to examples matching
296
- # these conditions e.g. `around(:example, :ui => true) { ... }` will
297
- # only run with examples or groups declared with `:ui => true`.
301
+ # @param conditions [Array<Symbol>, Hash] constrains this hook to
302
+ # examples matching these conditions e.g.
303
+ # `around(:example, :ui => true) { ... }` will only run with examples
304
+ # or groups declared with `:ui => true`. Symbols will be transformed
305
+ # into hash entries with `true` values.
298
306
  # @overload around(conditions, &block)
299
307
  # @param conditions [Hash] constrains this hook to examples matching
300
308
  # these conditions e.g. `around(:example, :ui => true) { ... }` will
@@ -304,7 +312,7 @@ module RSpec
304
312
  #
305
313
  # @note the syntax of `around` is similar to that of `before` and `after`
306
314
  # but the semantics are quite different. `before` and `after` hooks are
307
- # run in the context of of the examples with which they are associated,
315
+ # run in the context of the examples with which they are associated,
308
316
  # whereas `around` hooks are actually responsible for running the
309
317
  # examples. Consequently, `around` hooks do not have direct access to
310
318
  # resources that are made available within the examples and their
@@ -329,6 +337,15 @@ module RSpec
329
337
  # around(:example) {|ex| Database.transaction(&ex)}
330
338
  # around(:example) {|ex| FakeFS(&ex)}
331
339
  #
340
+ # ### Order
341
+ #
342
+ # The `around` hooks execute surrounding an example and its hooks.
343
+ #
344
+ # This means after any `before` context hooks, but before any `before`
345
+ # example hooks, and similarly after any `after` example hooks but before
346
+ # any `after` context hooks.
347
+ #
348
+ # They are not a synonym for `before`/`after`.
332
349
  def around(*args, &block)
333
350
  hooks.register :prepend, :around, *args, &block
334
351
  end
@@ -440,6 +457,11 @@ module RSpec
440
457
  "`#{position}(:suite)` hook, registered on an example " \
441
458
  "group, will be ignored."
442
459
  return
460
+ elsif scope == :context && position == :around
461
+ # TODO: consider making this an error in RSpec 4. For SemVer reasons,
462
+ # we are only warning in RSpec 3.
463
+ RSpec.warn_with "WARNING: `around(:context)` hooks are not supported and " \
464
+ "behave like `around(:example)."
443
465
  end
444
466
 
445
467
  hook = HOOK_TYPES[position][scope].new(block, options)