rspec-core 3.7.1 → 3.9.3

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 (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Changelog.md +116 -0
  5. data/README.md +18 -18
  6. data/lib/rspec/core.rb +1 -0
  7. data/lib/rspec/core/bisect/coordinator.rb +26 -30
  8. data/lib/rspec/core/bisect/example_minimizer.rb +12 -8
  9. data/lib/rspec/core/bisect/fork_runner.rb +138 -0
  10. data/lib/rspec/core/bisect/server.rb +5 -14
  11. data/lib/rspec/core/bisect/{runner.rb → shell_command.rb} +27 -70
  12. data/lib/rspec/core/bisect/shell_runner.rb +73 -0
  13. data/lib/rspec/core/bisect/utilities.rb +58 -0
  14. data/lib/rspec/core/configuration.rb +236 -79
  15. data/lib/rspec/core/configuration_options.rb +41 -4
  16. data/lib/rspec/core/did_you_mean.rb +46 -0
  17. data/lib/rspec/core/example.rb +18 -8
  18. data/lib/rspec/core/example_group.rb +33 -16
  19. data/lib/rspec/core/filter_manager.rb +1 -1
  20. data/lib/rspec/core/formatters.rb +14 -6
  21. data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
  22. data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
  23. data/lib/rspec/core/formatters/bisect_progress_formatter.rb +29 -16
  24. data/lib/rspec/core/formatters/deprecation_formatter.rb +3 -1
  25. data/lib/rspec/core/formatters/documentation_formatter.rb +35 -3
  26. data/lib/rspec/core/formatters/exception_presenter.rb +29 -6
  27. data/lib/rspec/core/formatters/failure_list_formatter.rb +23 -0
  28. data/lib/rspec/core/formatters/html_printer.rb +0 -2
  29. data/lib/rspec/core/formatters/protocol.rb +17 -17
  30. data/lib/rspec/core/formatters/syntax_highlighter.rb +19 -19
  31. data/lib/rspec/core/hooks.rb +44 -24
  32. data/lib/rspec/core/invocations.rb +9 -7
  33. data/lib/rspec/core/memoized_helpers.rb +33 -14
  34. data/lib/rspec/core/metadata.rb +2 -3
  35. data/lib/rspec/core/option_parser.rb +10 -3
  36. data/lib/rspec/core/profiler.rb +3 -1
  37. data/lib/rspec/core/rake_task.rb +22 -2
  38. data/lib/rspec/core/reporter.rb +11 -6
  39. data/lib/rspec/core/runner.rb +25 -14
  40. data/lib/rspec/core/shared_example_group.rb +5 -5
  41. data/lib/rspec/core/shell_escape.rb +2 -2
  42. data/lib/rspec/core/version.rb +1 -1
  43. data/lib/rspec/core/world.rb +14 -1
  44. metadata +25 -15
  45. metadata.gz.sig +0 -0
  46. data/lib/rspec/core/formatters/bisect_formatter.rb +0 -69
@@ -6,19 +6,14 @@ module RSpec
6
6
  # @private
7
7
  # Produces progress output while bisecting.
8
8
  class BisectProgressFormatter < BaseTextFormatter
9
- # We've named all events with a `bisect_` prefix to prevent naming collisions.
10
- Formatters.register self, :bisect_starting, :bisect_original_run_complete,
11
- :bisect_round_started, :bisect_individual_run_complete,
12
- :bisect_complete, :bisect_repro_command,
13
- :bisect_failed, :bisect_aborted,
14
- :bisect_round_ignoring_ids, :bisect_round_detected_multiple_culprits,
15
- :bisect_dependency_check_started, :bisect_dependency_check_passed,
16
- :bisect_dependency_check_failed
9
+ def initialize(output, bisect_runner)
10
+ super(output)
11
+ @bisect_runner = bisect_runner
12
+ end
17
13
 
18
14
  def bisect_starting(notification)
19
15
  @round_count = 0
20
- options = notification.original_cli_args.join(' ')
21
- output.puts "Bisect started using options: #{options.inspect}"
16
+ output.puts bisect_started_message(notification)
22
17
  output.print "Running suite to find failures..."
23
18
  end
24
19
 
@@ -40,6 +35,16 @@ module RSpec
40
35
 
41
36
  def bisect_dependency_check_failed(_notification)
42
37
  output.puts " failure(s) do not require any non-failures to run first"
38
+
39
+ if @bisect_runner == :fork
40
+ output.puts
41
+ output.puts "=" * 80
42
+ output.puts "NOTE: this bisect run used `config.bisect_runner = :fork`, which generally"
43
+ output.puts "provides significantly faster bisection runs than the old shell-based runner,"
44
+ output.puts "but may inaccurately report that no non-failures are required. If this result"
45
+ output.puts "is unexpected, consider setting `config.bisect_runner = :shell` and trying again."
46
+ output.puts "=" * 80
47
+ end
43
48
  end
44
49
 
45
50
  def bisect_round_started(notification, include_trailing_space=true)
@@ -85,16 +90,20 @@ module RSpec
85
90
  output.puts "\n\nBisect aborted!"
86
91
  output.puts "\nThe most minimal reproduction command discovered so far is:\n #{notification.repro}"
87
92
  end
93
+
94
+ private
95
+
96
+ def bisect_started_message(notification)
97
+ options = notification.original_cli_args.join(' ')
98
+ "Bisect started using options: #{options.inspect}"
99
+ end
88
100
  end
89
101
 
90
102
  # @private
91
- # Produces detailed debug output while bisecting. Used when
92
- # bisect is performed while the `DEBUG_RSPEC_BISECT` ENV var is used.
93
- # Designed to provide details for us when we need to troubleshoot bisect bugs.
103
+ # Produces detailed debug output while bisecting. Used when bisect is
104
+ # performed with `--bisect=verbose`. Designed to provide details for
105
+ # us when we need to troubleshoot bisect bugs.
94
106
  class BisectDebugFormatter < BisectProgressFormatter
95
- Formatters.register self, :bisect_original_run_complete, :bisect_individual_run_start,
96
- :bisect_individual_run_complete, :bisect_round_ignoring_ids
97
-
98
107
  def bisect_original_run_complete(notification)
99
108
  output.puts " (#{Helpers.format_duration(notification.duration)})"
100
109
 
@@ -138,6 +147,10 @@ module RSpec
138
147
  formatted_ids = organized_ids.map { |id| " - #{id}" }.join("\n")
139
148
  "#{description} (#{ids.size}):\n#{formatted_ids}"
140
149
  end
150
+
151
+ def bisect_started_message(notification)
152
+ "#{super} and bisect runner: #{notification.bisect_runner.inspect}"
153
+ end
141
154
  end
142
155
  end
143
156
  end
@@ -62,6 +62,7 @@ module RSpec
62
62
  TOO_MANY_WARNINGS_NOTICE = "Too many similar deprecation messages " \
63
63
  "reported, disregarding further reports. #{DEPRECATION_STREAM_NOTICE}"
64
64
 
65
+ # @private
65
66
  SpecifiedDeprecationMessage = Struct.new(:type) do
66
67
  def initialize(data)
67
68
  @message = data.message
@@ -80,7 +81,7 @@ module RSpec
80
81
 
81
82
  def output_formatted(str)
82
83
  return str unless str.lines.count > 1
83
- separator = "#{'-' * 80}"
84
+ separator = '-' * 80
84
85
  "#{separator}\n#{str.chomp}\n#{separator}"
85
86
  end
86
87
 
@@ -89,6 +90,7 @@ module RSpec
89
90
  end
90
91
  end
91
92
 
93
+ # @private
92
94
  GeneratedDeprecationMessage = Struct.new(:type) do
93
95
  def initialize(data)
94
96
  @data = data
@@ -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
@@ -81,7 +83,7 @@ module RSpec
81
83
 
82
84
  def fully_formatted_lines(failure_number, colorizer)
83
85
  lines = [
84
- description,
86
+ encoded_description(description),
85
87
  detail_formatter.call(example, colorizer),
86
88
  formatted_message_and_backtrace(colorizer),
87
89
  extra_detail_formatter.call(failure_number, colorizer),
@@ -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,10 +174,18 @@ 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
186
  lines = []
176
187
  lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
177
- encoded_string(exception.message.to_s).split("\n").each do |line|
188
+ encoded_string(exception_message_string(exception)).split("\n").each do |line|
178
189
  lines << (line.empty? ? line : " #{line}")
179
190
  end
180
191
  lines
@@ -244,6 +255,17 @@ module RSpec
244
255
  end
245
256
  end
246
257
 
258
+ if String.method_defined?(:encoding)
259
+ def encoded_description(description)
260
+ return if description.nil?
261
+ encoded_string(description)
262
+ end
263
+ else # for 1.8.7
264
+ def encoded_description(description)
265
+ description
266
+ end
267
+ end
268
+
247
269
  def exception_backtrace
248
270
  exception.backtrace || []
249
271
  end
@@ -379,6 +401,7 @@ module RSpec
379
401
  parent_bt[index] != child_bt[index]
380
402
  end
381
403
 
404
+ return child if index_before_first_common_frame.nil?
382
405
  return child if index_before_first_common_frame == -1
383
406
 
384
407
  child = child.dup
@@ -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
@@ -115,7 +115,6 @@ module RSpec
115
115
  "style=\"margin-left: #{(number_of_parents - 1) * 15}px;\""
116
116
  end
117
117
 
118
- # rubocop:disable LineLength
119
118
  REPORT_HEADER = <<-EOF
120
119
  <div class="rspec-report">
121
120
 
@@ -139,7 +138,6 @@ module RSpec
139
138
 
140
139
  <div class="results">
141
140
  EOF
142
- # rubocop:enable LineLength
143
141
 
144
142
  GLOBAL_SCRIPTS = <<-EOF
145
143
 
@@ -17,12 +17,12 @@ module RSpec
17
17
  # @see RSpec::Core::Formatters::BaseTextFormatter
18
18
  # @see RSpec::Core::Reporter
19
19
  class Protocol
20
- # @method initialize
20
+ # @method initialize(output)
21
21
  # @api public
22
22
  #
23
23
  # @param output [IO] the formatter output
24
24
 
25
- # @method start
25
+ # @method start(notification)
26
26
  # @api public
27
27
  # @group Suite Notifications
28
28
  #
@@ -35,7 +35,7 @@ module RSpec
35
35
  #
36
36
  # @param notification [Notifications::StartNotification]
37
37
 
38
- # @method example_group_started
38
+ # @method example_group_started(notification)
39
39
  # @api public
40
40
  # @group Group Notifications
41
41
  #
@@ -48,7 +48,7 @@ module RSpec
48
48
  # @param notification [Notifications::GroupNotification] containing example_group
49
49
  # subclass of {ExampleGroup}
50
50
 
51
- # @method example_group_finished
51
+ # @method example_group_finished(notification)
52
52
  # @api public
53
53
  # @group Group Notifications
54
54
  #
@@ -57,7 +57,7 @@ module RSpec
57
57
  # @param notification [Notifications::GroupNotification] containing example_group
58
58
  # subclass of {ExampleGroup}
59
59
 
60
- # @method example_started
60
+ # @method example_started(notification)
61
61
  # @api public
62
62
  # @group Example Notifications
63
63
  #
@@ -66,7 +66,7 @@ module RSpec
66
66
  # @param notification [Notifications::ExampleNotification] containing example subclass
67
67
  # of {Example}
68
68
 
69
- # @method example_finished
69
+ # @method example_finished(notification)
70
70
  # @api public
71
71
  # @group Example Notifications
72
72
  #
@@ -75,7 +75,7 @@ module RSpec
75
75
  # @param notification [Notifications::ExampleNotification] containing example subclass
76
76
  # of {Example}
77
77
 
78
- # @method example_passed
78
+ # @method example_passed(notification)
79
79
  # @api public
80
80
  # @group Example Notifications
81
81
  #
@@ -84,7 +84,7 @@ module RSpec
84
84
  # @param notification [Notifications::ExampleNotification] containing example subclass
85
85
  # of {Example}
86
86
 
87
- # @method example_pending
87
+ # @method example_pending(notification)
88
88
  # @api public
89
89
  # @group Example Notifications
90
90
  #
@@ -93,7 +93,7 @@ module RSpec
93
93
  # @param notification [Notifications::ExampleNotification] containing example subclass
94
94
  # of {Example}
95
95
 
96
- # @method example_failed
96
+ # @method example_failed(notification)
97
97
  # @api public
98
98
  # @group Example Notifications
99
99
  #
@@ -102,7 +102,7 @@ module RSpec
102
102
  # @param notification [Notifications::ExampleNotification] containing example subclass
103
103
  # of {Example}
104
104
 
105
- # @method message
105
+ # @method message(notification)
106
106
  # @api public
107
107
  # @group Suite Notifications
108
108
  #
@@ -110,7 +110,7 @@ module RSpec
110
110
  #
111
111
  # @param notification [Notifications::MessageNotification] containing message
112
112
 
113
- # @method stop
113
+ # @method stop(notification)
114
114
  # @api public
115
115
  # @group Suite Notifications
116
116
  #
@@ -119,7 +119,7 @@ module RSpec
119
119
  #
120
120
  # @param notification [Notifications::NullNotification]
121
121
 
122
- # @method start_dump
122
+ # @method start_dump(notification)
123
123
  # @api public
124
124
  # @group Suite Notifications
125
125
  #
@@ -130,7 +130,7 @@ module RSpec
130
130
  #
131
131
  # @param notification [Notifications::NullNotification]
132
132
 
133
- # @method dump_failures
133
+ # @method dump_failures(notification)
134
134
  # @api public
135
135
  # @group Suite Notifications
136
136
  #
@@ -138,7 +138,7 @@ module RSpec
138
138
  #
139
139
  # @param notification [Notifications::NullNotification]
140
140
 
141
- # @method dump_summary
141
+ # @method dump_summary(summary)
142
142
  # @api public
143
143
  # @group Suite Notifications
144
144
  #
@@ -148,7 +148,7 @@ module RSpec
148
148
  # @param summary [Notifications::SummaryNotification] containing duration,
149
149
  # example_count, failure_count and pending_count
150
150
 
151
- # @method dump_profile
151
+ # @method dump_profile(profile)
152
152
  # @api public
153
153
  # @group Suite Notifications
154
154
  #
@@ -158,7 +158,7 @@ module RSpec
158
158
  # @param profile [Notifications::ProfileNotification] containing duration,
159
159
  # slowest_examples and slowest_example_groups
160
160
 
161
- # @method dump_pending
161
+ # @method dump_pending(notification)
162
162
  # @api public
163
163
  # @group Suite Notifications
164
164
  #
@@ -167,7 +167,7 @@ module RSpec
167
167
  #
168
168
  # @param notification [Notifications::NullNotification]
169
169
 
170
- # @method close
170
+ # @method close(notification)
171
171
  # @api public
172
172
  # @group Suite Notifications
173
173
  #