rspec-core 3.0.4 → 3.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.document +1 -1
- data/.yardopts +2 -1
- data/Changelog.md +888 -2
- data/{License.txt → LICENSE.md} +6 -5
- data/README.md +165 -24
- data/lib/rspec/autorun.rb +1 -0
- data/lib/rspec/core/backtrace_formatter.rb +19 -20
- data/lib/rspec/core/bisect/coordinator.rb +62 -0
- data/lib/rspec/core/bisect/example_minimizer.rb +173 -0
- data/lib/rspec/core/bisect/fork_runner.rb +138 -0
- data/lib/rspec/core/bisect/server.rb +61 -0
- data/lib/rspec/core/bisect/shell_command.rb +126 -0
- data/lib/rspec/core/bisect/shell_runner.rb +73 -0
- data/lib/rspec/core/bisect/utilities.rb +69 -0
- data/lib/rspec/core/configuration.rb +1287 -246
- data/lib/rspec/core/configuration_options.rb +95 -35
- data/lib/rspec/core/did_you_mean.rb +46 -0
- data/lib/rspec/core/drb.rb +21 -12
- data/lib/rspec/core/dsl.rb +10 -6
- data/lib/rspec/core/example.rb +305 -113
- data/lib/rspec/core/example_group.rb +431 -223
- data/lib/rspec/core/example_status_persister.rb +235 -0
- data/lib/rspec/core/filter_manager.rb +86 -115
- data/lib/rspec/core/flat_map.rb +6 -4
- data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
- data/lib/rspec/core/formatters/base_formatter.rb +14 -116
- data/lib/rspec/core/formatters/base_text_formatter.rb +18 -21
- data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
- data/lib/rspec/core/formatters/bisect_progress_formatter.rb +157 -0
- data/lib/rspec/core/formatters/console_codes.rb +29 -18
- data/lib/rspec/core/formatters/deprecation_formatter.rb +16 -16
- data/lib/rspec/core/formatters/documentation_formatter.rb +49 -16
- data/lib/rspec/core/formatters/exception_presenter.rb +525 -0
- data/lib/rspec/core/formatters/failure_list_formatter.rb +23 -0
- data/lib/rspec/core/formatters/fallback_message_formatter.rb +28 -0
- data/lib/rspec/core/formatters/helpers.rb +45 -15
- data/lib/rspec/core/formatters/html_formatter.rb +33 -28
- data/lib/rspec/core/formatters/html_printer.rb +30 -20
- data/lib/rspec/core/formatters/html_snippet_extractor.rb +120 -0
- data/lib/rspec/core/formatters/json_formatter.rb +18 -9
- data/lib/rspec/core/formatters/profile_formatter.rb +10 -9
- data/lib/rspec/core/formatters/progress_formatter.rb +5 -4
- data/lib/rspec/core/formatters/protocol.rb +182 -0
- data/lib/rspec/core/formatters/snippet_extractor.rb +113 -82
- data/lib/rspec/core/formatters/syntax_highlighter.rb +91 -0
- data/lib/rspec/core/formatters.rb +81 -41
- data/lib/rspec/core/hooks.rb +314 -244
- data/lib/rspec/core/invocations.rb +87 -0
- data/lib/rspec/core/memoized_helpers.rb +161 -51
- data/lib/rspec/core/metadata.rb +132 -61
- data/lib/rspec/core/metadata_filter.rb +224 -64
- data/lib/rspec/core/minitest_assertions_adapter.rb +6 -3
- data/lib/rspec/core/mocking_adapters/flexmock.rb +4 -2
- data/lib/rspec/core/mocking_adapters/mocha.rb +11 -9
- data/lib/rspec/core/mocking_adapters/null.rb +2 -0
- data/lib/rspec/core/mocking_adapters/rr.rb +3 -1
- data/lib/rspec/core/mocking_adapters/rspec.rb +3 -1
- data/lib/rspec/core/notifications.rb +192 -206
- data/lib/rspec/core/option_parser.rb +174 -69
- data/lib/rspec/core/ordering.rb +48 -35
- data/lib/rspec/core/output_wrapper.rb +29 -0
- data/lib/rspec/core/pending.rb +25 -33
- data/lib/rspec/core/profiler.rb +34 -0
- data/lib/rspec/core/project_initializer/.rspec +0 -2
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +59 -39
- data/lib/rspec/core/project_initializer.rb +5 -3
- data/lib/rspec/core/rake_task.rb +99 -55
- data/lib/rspec/core/reporter.rb +128 -15
- data/lib/rspec/core/ruby_project.rb +14 -6
- data/lib/rspec/core/runner.rb +96 -45
- data/lib/rspec/core/sandbox.rb +37 -0
- data/lib/rspec/core/set.rb +54 -0
- data/lib/rspec/core/shared_example_group.rb +133 -43
- data/lib/rspec/core/shell_escape.rb +49 -0
- data/lib/rspec/core/test_unit_assertions_adapter.rb +4 -4
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/warnings.rb +6 -6
- data/lib/rspec/core/world.rb +172 -68
- data/lib/rspec/core.rb +66 -21
- data.tar.gz.sig +0 -0
- metadata +93 -69
- metadata.gz.sig +0 -0
- data/lib/rspec/core/backport_random.rb +0 -336
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
RSpec::Support.require_rspec_core "formatters/console_codes"
|
|
2
|
+
RSpec::Support.require_rspec_core "formatters/exception_presenter"
|
|
1
3
|
RSpec::Support.require_rspec_core "formatters/helpers"
|
|
4
|
+
RSpec::Support.require_rspec_core "shell_escape"
|
|
2
5
|
|
|
3
6
|
module RSpec::Core
|
|
4
7
|
# Notifications are value objects passed to formatters to provide them
|
|
5
8
|
# with information about a particular event of interest.
|
|
6
9
|
module Notifications
|
|
7
|
-
|
|
8
10
|
# @private
|
|
9
|
-
|
|
11
|
+
module NullColorizer
|
|
12
|
+
module_function
|
|
13
|
+
|
|
10
14
|
def wrap(line, _code_or_symbol)
|
|
11
15
|
line
|
|
12
16
|
end
|
|
@@ -31,17 +35,26 @@ module RSpec::Core
|
|
|
31
35
|
# end
|
|
32
36
|
#
|
|
33
37
|
# @attr example [RSpec::Core::Example] the current example
|
|
34
|
-
ExampleNotification = Struct.new(:example)
|
|
38
|
+
ExampleNotification = Struct.new(:example)
|
|
39
|
+
class ExampleNotification
|
|
35
40
|
# @private
|
|
36
41
|
def self.for(example)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
execution_result = example.execution_result
|
|
43
|
+
|
|
44
|
+
return SkippedExampleNotification.new(example) if execution_result.example_skipped?
|
|
45
|
+
return new(example) unless execution_result.status == :pending || execution_result.status == :failed
|
|
46
|
+
|
|
47
|
+
klass = if execution_result.pending_fixed?
|
|
48
|
+
PendingExampleFixedNotification
|
|
49
|
+
elsif execution_result.status == :pending
|
|
50
|
+
PendingExampleFailedAsExpectedNotification
|
|
51
|
+
else
|
|
52
|
+
FailedExampleNotification
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
klass.new(example)
|
|
44
56
|
end
|
|
57
|
+
|
|
45
58
|
private_class_method :new
|
|
46
59
|
end
|
|
47
60
|
|
|
@@ -54,62 +67,63 @@ module RSpec::Core
|
|
|
54
67
|
# end
|
|
55
68
|
#
|
|
56
69
|
class ExamplesNotification
|
|
57
|
-
|
|
58
70
|
def initialize(reporter)
|
|
59
71
|
@reporter = reporter
|
|
60
72
|
end
|
|
61
73
|
|
|
62
|
-
# @return [Array
|
|
74
|
+
# @return [Array<RSpec::Core::Example>] list of examples
|
|
63
75
|
def examples
|
|
64
76
|
@reporter.examples
|
|
65
77
|
end
|
|
66
78
|
|
|
67
|
-
# @return [Array
|
|
79
|
+
# @return [Array<RSpec::Core::Example>] list of failed examples
|
|
68
80
|
def failed_examples
|
|
69
81
|
@reporter.failed_examples
|
|
70
82
|
end
|
|
71
83
|
|
|
72
|
-
# @return [Array
|
|
84
|
+
# @return [Array<RSpec::Core::Example>] list of pending examples
|
|
73
85
|
def pending_examples
|
|
74
86
|
@reporter.pending_examples
|
|
75
87
|
end
|
|
76
88
|
|
|
77
|
-
# @return [Array
|
|
89
|
+
# @return [Array<RSpec::Core::Notifications::ExampleNotification>]
|
|
78
90
|
# returns examples as notifications
|
|
79
91
|
def notifications
|
|
80
|
-
@notifications ||=
|
|
92
|
+
@notifications ||= format_examples(examples)
|
|
81
93
|
end
|
|
82
94
|
|
|
83
|
-
# @return [Array
|
|
95
|
+
# @return [Array<RSpec::Core::Notifications::FailedExampleNotification>]
|
|
84
96
|
# returns failed examples as notifications
|
|
85
97
|
def failure_notifications
|
|
86
|
-
@failed_notifications ||=
|
|
98
|
+
@failed_notifications ||= format_examples(failed_examples)
|
|
87
99
|
end
|
|
88
100
|
|
|
89
|
-
# @return [
|
|
90
|
-
#
|
|
91
|
-
|
|
101
|
+
# @return [Array<RSpec::Core::Notifications::SkippedExampleNotification,
|
|
102
|
+
# RSpec::Core::Notifications::PendingExampleFailedAsExpectedNotification>]
|
|
103
|
+
# returns pending examples as notifications
|
|
104
|
+
def pending_notifications
|
|
105
|
+
@pending_notifications ||= format_examples(pending_examples)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @return [String] The list of failed examples, fully formatted in the way
|
|
109
|
+
# that RSpec's built-in formatters emit.
|
|
110
|
+
def fully_formatted_failed_examples(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
92
111
|
formatted = "\nFailures:\n"
|
|
93
112
|
|
|
94
113
|
failure_notifications.each_with_index do |failure, index|
|
|
95
|
-
formatted
|
|
114
|
+
formatted += failure.fully_formatted(index.next, colorizer)
|
|
96
115
|
end
|
|
97
116
|
|
|
98
117
|
formatted
|
|
99
118
|
end
|
|
100
119
|
|
|
101
|
-
# @return [String] The list of pending examples, fully formatted in the
|
|
102
|
-
# RSpec's built-in formatters emit.
|
|
103
|
-
def fully_formatted_pending_examples(colorizer
|
|
104
|
-
formatted = "\nPending
|
|
105
|
-
|
|
106
|
-
pending_examples.each do |example|
|
|
107
|
-
formatted_caller = RSpec.configuration.backtrace_formatter.backtrace_line(example.location)
|
|
120
|
+
# @return [String] The list of pending examples, fully formatted in the
|
|
121
|
+
# way that RSpec's built-in formatters emit.
|
|
122
|
+
def fully_formatted_pending_examples(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
123
|
+
formatted = "\nPending: (Failures listed here are expected and do not affect your suite's status)\n".dup
|
|
108
124
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
" # #{colorizer.wrap(example.execution_result.pending_message, :detail)}\n" <<
|
|
112
|
-
" # #{colorizer.wrap(formatted_caller, :detail)}\n"
|
|
125
|
+
pending_notifications.each_with_index do |notification, index|
|
|
126
|
+
formatted << notification.fully_formatted(index.next, colorizer)
|
|
113
127
|
end
|
|
114
128
|
|
|
115
129
|
formatted
|
|
@@ -117,16 +131,16 @@ module RSpec::Core
|
|
|
117
131
|
|
|
118
132
|
private
|
|
119
133
|
|
|
120
|
-
def
|
|
134
|
+
def format_examples(examples)
|
|
121
135
|
examples.map do |example|
|
|
122
136
|
ExampleNotification.for(example)
|
|
123
137
|
end
|
|
124
138
|
end
|
|
125
|
-
|
|
126
139
|
end
|
|
127
140
|
|
|
128
141
|
# The `FailedExampleNotification` extends `ExampleNotification` with
|
|
129
|
-
# things useful for
|
|
142
|
+
# things useful for examples that have failure info -- typically a
|
|
143
|
+
# failed or pending spec.
|
|
130
144
|
#
|
|
131
145
|
# @example
|
|
132
146
|
# def example_failed(notification)
|
|
@@ -142,173 +156,97 @@ module RSpec::Core
|
|
|
142
156
|
|
|
143
157
|
# @return [Exception] The example failure
|
|
144
158
|
def exception
|
|
145
|
-
|
|
159
|
+
@exception_presenter.exception
|
|
146
160
|
end
|
|
147
161
|
|
|
148
162
|
# @return [String] The example description
|
|
149
163
|
def description
|
|
150
|
-
|
|
164
|
+
@exception_presenter.description
|
|
151
165
|
end
|
|
152
166
|
|
|
153
167
|
# Returns the message generated for this failure line by line.
|
|
154
168
|
#
|
|
155
|
-
# @return [Array
|
|
169
|
+
# @return [Array<String>] The example failure message
|
|
156
170
|
def message_lines
|
|
157
|
-
|
|
171
|
+
@exception_presenter.message_lines
|
|
158
172
|
end
|
|
159
173
|
|
|
160
174
|
# Returns the message generated for this failure colorized line by line.
|
|
161
175
|
#
|
|
162
176
|
# @param colorizer [#wrap] An object to colorize the message_lines by
|
|
163
|
-
# @return [Array
|
|
164
|
-
def colorized_message_lines(colorizer
|
|
165
|
-
|
|
166
|
-
colorizer.wrap line, RSpec.configuration.failure_color
|
|
167
|
-
end
|
|
177
|
+
# @return [Array<String>] The example failure message colorized
|
|
178
|
+
def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
179
|
+
@exception_presenter.colorized_message_lines(colorizer)
|
|
168
180
|
end
|
|
169
181
|
|
|
170
182
|
# Returns the failures formatted backtrace.
|
|
171
183
|
#
|
|
172
|
-
# @return [Array
|
|
184
|
+
# @return [Array<String>] the examples backtrace lines
|
|
173
185
|
def formatted_backtrace
|
|
174
|
-
|
|
186
|
+
@exception_presenter.formatted_backtrace
|
|
175
187
|
end
|
|
176
188
|
|
|
177
189
|
# Returns the failures colorized formatted backtrace.
|
|
178
190
|
#
|
|
179
191
|
# @param colorizer [#wrap] An object to colorize the message_lines by
|
|
180
|
-
# @return [Array
|
|
181
|
-
def colorized_formatted_backtrace(colorizer
|
|
182
|
-
|
|
183
|
-
colorizer.wrap "# #{backtrace_info}", RSpec.configuration.detail_color
|
|
184
|
-
end
|
|
192
|
+
# @return [Array<String>] the examples colorized backtrace lines
|
|
193
|
+
def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
194
|
+
@exception_presenter.colorized_formatted_backtrace(colorizer)
|
|
185
195
|
end
|
|
186
196
|
|
|
187
197
|
# @return [String] The failure information fully formatted in the way that
|
|
188
198
|
# RSpec's built-in formatters emit.
|
|
189
|
-
def fully_formatted(failure_number, colorizer
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
colorized_message_lines(colorizer).each do |line|
|
|
193
|
-
formatted << " #{line}\n"
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
colorized_formatted_backtrace(colorizer).each do |line|
|
|
197
|
-
formatted << " #{line}\n"
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
formatted
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
private
|
|
204
|
-
|
|
205
|
-
def backtrace_formatter
|
|
206
|
-
RSpec.configuration.backtrace_formatter
|
|
199
|
+
def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
200
|
+
@exception_presenter.fully_formatted(failure_number, colorizer)
|
|
207
201
|
end
|
|
208
202
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
203
|
+
# @return [Array<string>] The failure information fully formatted in the way that
|
|
204
|
+
# RSpec's built-in formatters emit, split by line.
|
|
205
|
+
def fully_formatted_lines(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
206
|
+
@exception_presenter.fully_formatted_lines(failure_number, colorizer)
|
|
213
207
|
end
|
|
214
208
|
|
|
215
|
-
|
|
216
|
-
@failure_lines ||=
|
|
217
|
-
begin
|
|
218
|
-
lines = ["Failure/Error: #{read_failed_line.strip}"]
|
|
219
|
-
lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
|
|
220
|
-
exception.message.to_s.split("\n").each do |line|
|
|
221
|
-
lines << " #{line}" if exception.message
|
|
222
|
-
end
|
|
223
|
-
lines
|
|
224
|
-
end
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def add_shared_group_line(lines, colorizer)
|
|
228
|
-
unless shared_group_line == ""
|
|
229
|
-
lines << colorizer.wrap(shared_group_line, RSpec.configuration.default_color)
|
|
230
|
-
end
|
|
231
|
-
lines
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def shared_group
|
|
235
|
-
@shared_group ||= group_and_parent_groups.find { |group| group.metadata[:shared_group_name] }
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
def shared_group_line
|
|
239
|
-
@shared_group_line ||=
|
|
240
|
-
if shared_group
|
|
241
|
-
"Shared Example Group: \"#{shared_group.metadata[:shared_group_name]}\"" +
|
|
242
|
-
" called from #{backtrace_formatter.backtrace_line(shared_group.location)}"
|
|
243
|
-
else
|
|
244
|
-
""
|
|
245
|
-
end
|
|
246
|
-
end
|
|
209
|
+
private
|
|
247
210
|
|
|
248
|
-
def
|
|
249
|
-
|
|
211
|
+
def initialize(example, exception_presenter=Formatters::ExceptionPresenter::Factory.new(example).build)
|
|
212
|
+
@exception_presenter = exception_presenter
|
|
213
|
+
super(example)
|
|
250
214
|
end
|
|
215
|
+
end
|
|
251
216
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
return "Unable to find matching line from backtrace"
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
|
|
258
|
-
|
|
259
|
-
if File.exist?(file_path)
|
|
260
|
-
File.readlines(file_path)[line_number.to_i - 1] ||
|
|
261
|
-
"Unable to find matching line in #{file_path}"
|
|
262
|
-
else
|
|
263
|
-
"Unable to find #{file_path} to read failed line"
|
|
264
|
-
end
|
|
265
|
-
rescue SecurityError
|
|
266
|
-
"Unable to read failed line"
|
|
267
|
-
end
|
|
217
|
+
# @deprecated Use {FailedExampleNotification} instead.
|
|
218
|
+
class PendingExampleFixedNotification < FailedExampleNotification; end
|
|
268
219
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
exception.backtrace.detect do |line|
|
|
272
|
-
match = line.match(/(.+?):(\d+)(|:\d+)/)
|
|
273
|
-
match && match[1].downcase == path.downcase
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
end
|
|
220
|
+
# @deprecated Use {FailedExampleNotification} instead.
|
|
221
|
+
class PendingExampleFailedAsExpectedNotification < FailedExampleNotification; end
|
|
277
222
|
|
|
278
|
-
# The `
|
|
279
|
-
# things useful for specs that
|
|
223
|
+
# The `SkippedExampleNotification` extends `ExampleNotification` with
|
|
224
|
+
# things useful for specs that are skipped.
|
|
280
225
|
#
|
|
281
226
|
# @attr [RSpec::Core::Example] example the current example
|
|
282
227
|
# @see ExampleNotification
|
|
283
|
-
class
|
|
228
|
+
class SkippedExampleNotification < ExampleNotification
|
|
284
229
|
public_class_method :new
|
|
285
230
|
|
|
286
|
-
#
|
|
287
|
-
#
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
"#{example.full_description} FIXED"
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
# Returns the message generated for this failure line by line.
|
|
294
|
-
#
|
|
295
|
-
# @return [Array(String)] The example failure message
|
|
296
|
-
def message_lines
|
|
297
|
-
["Expected pending '#{example.execution_result.pending_message}' to fail. No Error was raised."]
|
|
298
|
-
end
|
|
231
|
+
# @return [String] The pending detail fully formatted in the way that
|
|
232
|
+
# RSpec's built-in formatters emit.
|
|
233
|
+
def fully_formatted(pending_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
234
|
+
formatted_caller = RSpec.configuration.backtrace_formatter.backtrace_line(example.location)
|
|
299
235
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
236
|
+
[
|
|
237
|
+
colorizer.wrap("\n #{pending_number}) #{example.full_description}", :pending),
|
|
238
|
+
"\n ",
|
|
239
|
+
Formatters::ExceptionPresenter::PENDING_DETAIL_FORMATTER.call(example, colorizer),
|
|
240
|
+
"\n",
|
|
241
|
+
colorizer.wrap(" # #{formatted_caller}\n", :detail)
|
|
242
|
+
].join("")
|
|
306
243
|
end
|
|
307
244
|
end
|
|
308
245
|
|
|
309
|
-
# The `GroupNotification` represents notifications sent by the reporter
|
|
310
|
-
# contain information about the currently running (or soon to be)
|
|
311
|
-
# It is used by formatters to access information about that
|
|
246
|
+
# The `GroupNotification` represents notifications sent by the reporter
|
|
247
|
+
# which contain information about the currently running (or soon to be)
|
|
248
|
+
# example group. It is used by formatters to access information about that
|
|
249
|
+
# group.
|
|
312
250
|
#
|
|
313
251
|
# @example
|
|
314
252
|
# def example_group_started(notification)
|
|
@@ -324,11 +262,12 @@ module RSpec::Core
|
|
|
324
262
|
MessageNotification = Struct.new(:message)
|
|
325
263
|
|
|
326
264
|
# The `SeedNotification` holds the seed used to randomize examples and
|
|
327
|
-
#
|
|
265
|
+
# whether that seed has been used or not.
|
|
328
266
|
#
|
|
329
267
|
# @attr seed [Fixnum] the seed used to randomize ordering
|
|
330
|
-
# @attr used [Boolean]
|
|
331
|
-
SeedNotification = Struct.new(:seed, :used)
|
|
268
|
+
# @attr used [Boolean] whether the seed has been used or not
|
|
269
|
+
SeedNotification = Struct.new(:seed, :used)
|
|
270
|
+
class SeedNotification
|
|
332
271
|
# @api
|
|
333
272
|
# @return [Boolean] has the seed been used?
|
|
334
273
|
def seed_used?
|
|
@@ -339,7 +278,7 @@ module RSpec::Core
|
|
|
339
278
|
# @return [String] The seed information fully formatted in the way that
|
|
340
279
|
# RSpec's built-in formatters emit.
|
|
341
280
|
def fully_formatted
|
|
342
|
-
"\nRandomized with seed #{seed}\n
|
|
281
|
+
"\nRandomized with seed #{seed}\n"
|
|
343
282
|
end
|
|
344
283
|
end
|
|
345
284
|
|
|
@@ -348,13 +287,18 @@ module RSpec::Core
|
|
|
348
287
|
# of the test run.
|
|
349
288
|
#
|
|
350
289
|
# @attr duration [Float] the time taken (in seconds) to run the suite
|
|
351
|
-
# @attr examples [Array
|
|
352
|
-
# @attr failed_examples [Array
|
|
353
|
-
# @attr pending_examples [Array
|
|
290
|
+
# @attr examples [Array<RSpec::Core::Example>] the examples run
|
|
291
|
+
# @attr failed_examples [Array<RSpec::Core::Example>] the failed examples
|
|
292
|
+
# @attr pending_examples [Array<RSpec::Core::Example>] the pending examples
|
|
354
293
|
# @attr load_time [Float] the number of seconds taken to boot RSpec
|
|
355
294
|
# and load the spec files
|
|
356
|
-
|
|
357
|
-
|
|
295
|
+
# @attr errors_outside_of_examples_count [Integer] the number of errors that
|
|
296
|
+
# have occurred processing
|
|
297
|
+
# the spec suite
|
|
298
|
+
SummaryNotification = Struct.new(:duration, :examples, :failed_examples,
|
|
299
|
+
:pending_examples, :load_time,
|
|
300
|
+
:errors_outside_of_examples_count)
|
|
301
|
+
class SummaryNotification
|
|
358
302
|
# @api
|
|
359
303
|
# @return [Fixnum] the number of examples run
|
|
360
304
|
def example_count
|
|
@@ -376,9 +320,16 @@ module RSpec::Core
|
|
|
376
320
|
# @api
|
|
377
321
|
# @return [String] A line summarising the result totals of the spec run.
|
|
378
322
|
def totals_line
|
|
379
|
-
summary = Formatters::Helpers.pluralize(example_count, "example")
|
|
380
|
-
|
|
381
|
-
summary
|
|
323
|
+
summary = Formatters::Helpers.pluralize(example_count, "example") +
|
|
324
|
+
", " + Formatters::Helpers.pluralize(failure_count, "failure")
|
|
325
|
+
summary += ", #{pending_count} pending" if pending_count > 0
|
|
326
|
+
if errors_outside_of_examples_count > 0
|
|
327
|
+
summary += (
|
|
328
|
+
", " +
|
|
329
|
+
Formatters::Helpers.pluralize(errors_outside_of_examples_count, "error") +
|
|
330
|
+
" occurred outside of examples"
|
|
331
|
+
)
|
|
332
|
+
end
|
|
382
333
|
summary
|
|
383
334
|
end
|
|
384
335
|
|
|
@@ -391,8 +342,8 @@ module RSpec::Core
|
|
|
391
342
|
# @param colorizer [#wrap] An object which supports wrapping text with
|
|
392
343
|
# specific colors.
|
|
393
344
|
# @return [String] A colorized results line.
|
|
394
|
-
def colorized_totals_line(colorizer
|
|
395
|
-
if failure_count > 0
|
|
345
|
+
def colorized_totals_line(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
346
|
+
if failure_count > 0 || errors_outside_of_examples_count > 0
|
|
396
347
|
colorizer.wrap(totals_line, RSpec.configuration.failure_color)
|
|
397
348
|
elsif pending_count > 0
|
|
398
349
|
colorizer.wrap(totals_line, RSpec.configuration.pending_color)
|
|
@@ -408,50 +359,81 @@ module RSpec::Core
|
|
|
408
359
|
# @param colorizer [#wrap] An object which supports wrapping text with
|
|
409
360
|
# specific colors.
|
|
410
361
|
# @return [String] A colorized summary line.
|
|
411
|
-
def colorized_rerun_commands(colorizer
|
|
362
|
+
def colorized_rerun_commands(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
412
363
|
"\nFailed examples:\n\n" +
|
|
413
364
|
failed_examples.map do |example|
|
|
414
|
-
colorizer.wrap("rspec #{example
|
|
415
|
-
colorizer.wrap("# #{example.full_description}",
|
|
365
|
+
colorizer.wrap("rspec #{rerun_argument_for(example)}", RSpec.configuration.failure_color) + " " +
|
|
366
|
+
colorizer.wrap("# #{example.full_description}", RSpec.configuration.detail_color)
|
|
416
367
|
end.join("\n")
|
|
417
368
|
end
|
|
418
369
|
|
|
419
|
-
# @return [String] a formatted version of the time it took to run the
|
|
370
|
+
# @return [String] a formatted version of the time it took to run the
|
|
371
|
+
# suite
|
|
420
372
|
def formatted_duration
|
|
421
373
|
Formatters::Helpers.format_duration(duration)
|
|
422
374
|
end
|
|
423
375
|
|
|
424
|
-
# @return [String] a formatted version of the time it took to boot RSpec
|
|
425
|
-
# load the spec files
|
|
376
|
+
# @return [String] a formatted version of the time it took to boot RSpec
|
|
377
|
+
# and load the spec files
|
|
426
378
|
def formatted_load_time
|
|
427
379
|
Formatters::Helpers.format_duration(load_time)
|
|
428
380
|
end
|
|
429
381
|
|
|
430
382
|
# @return [String] The summary information fully formatted in the way that
|
|
431
383
|
# RSpec's built-in formatters emit.
|
|
432
|
-
def fully_formatted(colorizer
|
|
384
|
+
def fully_formatted(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
|
433
385
|
formatted = "\nFinished in #{formatted_duration} " \
|
|
434
386
|
"(files took #{formatted_load_time} to load)\n" \
|
|
435
387
|
"#{colorized_totals_line(colorizer)}\n"
|
|
436
388
|
|
|
437
389
|
unless failed_examples.empty?
|
|
438
|
-
formatted
|
|
390
|
+
formatted += (colorized_rerun_commands(colorizer) + "\n")
|
|
439
391
|
end
|
|
440
392
|
|
|
441
393
|
formatted
|
|
442
394
|
end
|
|
395
|
+
|
|
396
|
+
private
|
|
397
|
+
|
|
398
|
+
include RSpec::Core::ShellEscape
|
|
399
|
+
|
|
400
|
+
def rerun_argument_for(example)
|
|
401
|
+
location = example.location_rerun_argument
|
|
402
|
+
return location unless duplicate_rerun_locations.include?(location)
|
|
403
|
+
conditionally_quote(example.id)
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def duplicate_rerun_locations
|
|
407
|
+
@duplicate_rerun_locations ||= begin
|
|
408
|
+
locations = RSpec.world.all_examples.map(&:location_rerun_argument)
|
|
409
|
+
|
|
410
|
+
Set.new.tap do |s|
|
|
411
|
+
locations.group_by { |l| l }.each do |l, ls|
|
|
412
|
+
s << l if ls.count > 1
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
end
|
|
443
417
|
end
|
|
444
418
|
|
|
445
|
-
# The `ProfileNotification` holds information about the results of running
|
|
446
|
-
#
|
|
419
|
+
# The `ProfileNotification` holds information about the results of running a
|
|
420
|
+
# test suite when profiling is enabled. It is used by formatters to provide
|
|
447
421
|
# information at the end of the test run for profiling information.
|
|
448
422
|
#
|
|
449
423
|
# @attr duration [Float] the time taken (in seconds) to run the suite
|
|
450
|
-
# @attr examples [Array
|
|
424
|
+
# @attr examples [Array<RSpec::Core::Example>] the examples run
|
|
451
425
|
# @attr number_of_examples [Fixnum] the number of examples to profile
|
|
452
|
-
|
|
426
|
+
# @attr example_groups [Array<RSpec::Core::Profiler>] example groups run
|
|
427
|
+
class ProfileNotification
|
|
428
|
+
def initialize(duration, examples, number_of_examples, example_groups)
|
|
429
|
+
@duration = duration
|
|
430
|
+
@examples = examples
|
|
431
|
+
@number_of_examples = number_of_examples
|
|
432
|
+
@example_groups = example_groups
|
|
433
|
+
end
|
|
434
|
+
attr_reader :duration, :examples, :number_of_examples
|
|
453
435
|
|
|
454
|
-
# @return [Array
|
|
436
|
+
# @return [Array<RSpec::Core::Example>] the slowest examples
|
|
455
437
|
def slowest_examples
|
|
456
438
|
@slowest_examples ||=
|
|
457
439
|
examples.sort_by do |example|
|
|
@@ -476,7 +458,7 @@ module RSpec::Core
|
|
|
476
458
|
end
|
|
477
459
|
end
|
|
478
460
|
|
|
479
|
-
# @return [Array
|
|
461
|
+
# @return [Array<RSpec::Core::Example>] the slowest example groups
|
|
480
462
|
def slowest_groups
|
|
481
463
|
@slowest_groups ||= calculate_slowest_groups
|
|
482
464
|
end
|
|
@@ -484,39 +466,30 @@ module RSpec::Core
|
|
|
484
466
|
private
|
|
485
467
|
|
|
486
468
|
def calculate_slowest_groups
|
|
487
|
-
example_groups = {}
|
|
488
|
-
|
|
489
|
-
examples.each do |example|
|
|
490
|
-
location = example.example_group.parent_groups.last.metadata[:location]
|
|
491
|
-
|
|
492
|
-
location_hash = example_groups[location] ||= Hash.new(0)
|
|
493
|
-
location_hash[:total_time] += example.execution_result.run_time
|
|
494
|
-
location_hash[:count] += 1
|
|
495
|
-
unless location_hash.has_key?(:description)
|
|
496
|
-
location_hash[:description] = example.example_group.top_level_description
|
|
497
|
-
end
|
|
498
|
-
end
|
|
499
|
-
|
|
500
469
|
# stop if we've only one example group
|
|
501
|
-
return {} if example_groups.keys.length <= 1
|
|
470
|
+
return {} if @example_groups.keys.length <= 1
|
|
502
471
|
|
|
503
|
-
example_groups.each_value do |hash|
|
|
472
|
+
@example_groups.each_value do |hash|
|
|
504
473
|
hash[:average] = hash[:total_time].to_f / hash[:count]
|
|
505
474
|
end
|
|
506
475
|
|
|
507
|
-
example_groups.sort_by { |_, hash| -hash[:average] }.first(number_of_examples)
|
|
476
|
+
groups = @example_groups.sort_by { |_, hash| -hash[:average] }.first(number_of_examples)
|
|
477
|
+
groups.map { |group, data| [group.location, data] }
|
|
508
478
|
end
|
|
509
479
|
end
|
|
510
480
|
|
|
511
481
|
# The `DeprecationNotification` is issued by the reporter when a deprecated
|
|
512
|
-
# part of RSpec is encountered. It represents information about the
|
|
513
|
-
# call site.
|
|
482
|
+
# part of RSpec is encountered. It represents information about the
|
|
483
|
+
# deprecated call site.
|
|
514
484
|
#
|
|
515
485
|
# @attr message [String] A custom message about the deprecation
|
|
516
|
-
# @attr deprecated [String] A custom message about the deprecation (alias of
|
|
486
|
+
# @attr deprecated [String] A custom message about the deprecation (alias of
|
|
487
|
+
# message)
|
|
517
488
|
# @attr replacement [String] An optional replacement for the deprecation
|
|
518
|
-
# @attr call_site [String] An optional call site from which the deprecation
|
|
519
|
-
|
|
489
|
+
# @attr call_site [String] An optional call site from which the deprecation
|
|
490
|
+
# was issued
|
|
491
|
+
DeprecationNotification = Struct.new(:deprecated, :message, :replacement, :call_site)
|
|
492
|
+
class DeprecationNotification
|
|
520
493
|
private_class_method :new
|
|
521
494
|
|
|
522
495
|
# @api
|
|
@@ -531,5 +504,18 @@ module RSpec::Core
|
|
|
531
504
|
class NullNotification
|
|
532
505
|
end
|
|
533
506
|
|
|
507
|
+
# `CustomNotification` is used when sending custom events to formatters /
|
|
508
|
+
# other registered listeners, it creates attributes based on supplied hash
|
|
509
|
+
# of options.
|
|
510
|
+
class CustomNotification < Struct
|
|
511
|
+
# @param options [Hash] A hash of method / value pairs to create on this notification
|
|
512
|
+
# @return [CustomNotification]
|
|
513
|
+
#
|
|
514
|
+
# Build a custom notification based on the supplied option key / values.
|
|
515
|
+
def self.for(options={})
|
|
516
|
+
return NullNotification if options.keys.empty?
|
|
517
|
+
new(*options.keys).new(*options.values)
|
|
518
|
+
end
|
|
519
|
+
end
|
|
534
520
|
end
|
|
535
521
|
end
|