minitest 5.16.3 → 5.25.1
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.rdoc +176 -1
- data/Manifest.txt +3 -0
- data/README.rdoc +26 -25
- data/Rakefile +7 -0
- data/lib/hoe/minitest.rb +2 -1
- data/lib/minitest/assertions.rb +126 -79
- data/lib/minitest/autorun.rb +0 -7
- data/lib/minitest/benchmark.rb +6 -9
- data/lib/minitest/compress.rb +94 -0
- data/lib/minitest/error_on_warning.rb +11 -0
- data/lib/minitest/expectations.rb +18 -0
- data/lib/minitest/manual_plugins.rb +16 -0
- data/lib/minitest/mock.rb +23 -17
- data/lib/minitest/parallel.rb +5 -5
- data/lib/minitest/pride_plugin.rb +16 -23
- data/lib/minitest/spec.rb +10 -4
- data/lib/minitest/test.rb +22 -37
- data/lib/minitest/test_task.rb +24 -22
- data/lib/minitest.rb +296 -148
- data/test/minitest/metametameta.rb +32 -18
- data/test/minitest/test_minitest_assertions.rb +269 -140
- data/test/minitest/test_minitest_benchmark.rb +1 -1
- data/test/minitest/test_minitest_mock.rb +89 -77
- data/test/minitest/test_minitest_reporter.rb +139 -15
- data/test/minitest/test_minitest_spec.rb +130 -55
- data/test/minitest/test_minitest_test.rb +200 -116
- data/test/minitest/test_minitest_test_task.rb +18 -7
- data.tar.gz.sig +0 -0
- metadata +20 -16
- metadata.gz.sig +0 -0
data/lib/minitest.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
require "optparse"
|
2
|
-
require "thread"
|
3
|
-
require "mutex_m"
|
4
|
-
require "minitest/parallel"
|
5
2
|
require "stringio"
|
6
3
|
require "etc"
|
7
4
|
|
5
|
+
require_relative "minitest/parallel"
|
6
|
+
require_relative "minitest/compress"
|
7
|
+
|
8
8
|
##
|
9
9
|
# :include: README.rdoc
|
10
10
|
|
11
11
|
module Minitest
|
12
|
-
VERSION = "5.
|
12
|
+
VERSION = "5.25.1" # :nodoc:
|
13
13
|
|
14
14
|
@@installed_at_exit ||= false
|
15
15
|
@@after_run = []
|
@@ -32,7 +32,7 @@ module Minitest
|
|
32
32
|
|
33
33
|
cattr_accessor :parallel_executor
|
34
34
|
|
35
|
-
warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"]
|
35
|
+
warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"] && ENV["N"].to_i > 0
|
36
36
|
n_threads = (ENV["MT_CPU"] || ENV["N"] || Etc.nprocessors).to_i
|
37
37
|
|
38
38
|
self.parallel_executor = Parallel::Executor.new n_threads
|
@@ -60,13 +60,15 @@ module Minitest
|
|
60
60
|
cattr_accessor :info_signal
|
61
61
|
self.info_signal = "INFO"
|
62
62
|
|
63
|
+
cattr_accessor :allow_fork
|
64
|
+
self.allow_fork = false
|
65
|
+
|
63
66
|
##
|
64
67
|
# Registers Minitest to run at process exit
|
65
68
|
|
66
69
|
def self.autorun
|
67
|
-
|
68
|
-
Warning[
|
69
|
-
end
|
70
|
+
Warning[:deprecated] = true if
|
71
|
+
Object.const_defined?(:Warning) && Warning.respond_to?(:[]=)
|
70
72
|
|
71
73
|
at_exit {
|
72
74
|
next if $! and not ($!.kind_of? SystemExit and $!.success?)
|
@@ -75,7 +77,7 @@ module Minitest
|
|
75
77
|
|
76
78
|
pid = Process.pid
|
77
79
|
at_exit {
|
78
|
-
next if Process.pid != pid
|
80
|
+
next if !Minitest.allow_fork && Process.pid != pid
|
79
81
|
@@after_run.reverse_each(&:call)
|
80
82
|
exit exit_code || false
|
81
83
|
}
|
@@ -95,20 +97,19 @@ module Minitest
|
|
95
97
|
@@after_run << block
|
96
98
|
end
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
##
|
101
|
+
# Register a plugin to be used. Does NOT require / load it.
|
102
|
+
|
103
|
+
def self.register_plugin name_or_mod
|
104
|
+
self.extensions << name_or_mod
|
105
|
+
nil
|
103
106
|
end
|
104
107
|
|
105
108
|
def self.load_plugins # :nodoc:
|
106
|
-
return unless
|
109
|
+
return unless defined? Gem
|
107
110
|
|
108
111
|
seen = {}
|
109
112
|
|
110
|
-
require "rubygems" unless defined? Gem
|
111
|
-
|
112
113
|
Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
|
113
114
|
name = File.basename plugin_path, "_plugin.rb"
|
114
115
|
|
@@ -120,72 +121,27 @@ module Minitest
|
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
# klass.new(runnable_method).run
|
139
|
-
|
140
|
-
def self.run args = []
|
141
|
-
self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
|
142
|
-
|
143
|
-
options = process_args args
|
144
|
-
|
145
|
-
Minitest.seed = options[:seed]
|
146
|
-
srand Minitest.seed
|
147
|
-
|
148
|
-
reporter = CompositeReporter.new
|
149
|
-
reporter << SummaryReporter.new(options[:io], options)
|
150
|
-
reporter << ProgressReporter.new(options[:io], options)
|
151
|
-
|
152
|
-
self.reporter = reporter # this makes it available to plugins
|
153
|
-
self.init_plugins options
|
154
|
-
self.reporter = nil # runnables shouldn't depend on the reporter, ever
|
155
|
-
|
156
|
-
self.parallel_executor.start if parallel_executor.respond_to?(:start)
|
157
|
-
reporter.start
|
158
|
-
begin
|
159
|
-
__run reporter, options
|
160
|
-
rescue Interrupt
|
161
|
-
warn "Interrupted. Exiting..."
|
124
|
+
def self.init_plugins options # :nodoc:
|
125
|
+
self.extensions.each do |mod_or_meth|
|
126
|
+
case mod_or_meth
|
127
|
+
when Symbol, String then
|
128
|
+
name = mod_or_meth
|
129
|
+
msg = "plugin_#{name}_init"
|
130
|
+
next unless self.respond_to? msg
|
131
|
+
send msg, options
|
132
|
+
when Module then
|
133
|
+
recv = mod_or_meth
|
134
|
+
next unless recv.respond_to? :minitest_plugin_init
|
135
|
+
recv.minitest_plugin_init options
|
136
|
+
else
|
137
|
+
raise ArgumentError, "plugin is %p, but it must be a symbol, string or module" % [mod_or_meth]
|
138
|
+
end
|
162
139
|
end
|
163
|
-
self.parallel_executor.shutdown
|
164
|
-
reporter.report
|
165
|
-
|
166
|
-
reporter.passed?
|
167
|
-
end
|
168
|
-
|
169
|
-
##
|
170
|
-
# Internal run method. Responsible for telling all Runnable
|
171
|
-
# sub-classes to run.
|
172
|
-
|
173
|
-
def self.__run reporter, options
|
174
|
-
suites = Runnable.runnables.shuffle
|
175
|
-
parallel, serial = suites.partition { |s| s.test_order == :parallel }
|
176
|
-
|
177
|
-
# If we run the parallel tests before the serial tests, the parallel tests
|
178
|
-
# could run in parallel with the serial tests. This would be bad because
|
179
|
-
# the serial tests won't lock around Reporter#record. Run the serial tests
|
180
|
-
# first, so that after they complete, the parallel tests will lock when
|
181
|
-
# recording results.
|
182
|
-
serial.map { |suite| suite.run reporter, options } +
|
183
|
-
parallel.map { |suite| suite.run reporter, options }
|
184
140
|
end
|
185
141
|
|
186
142
|
def self.process_args args = [] # :nodoc:
|
187
143
|
options = {
|
188
|
-
|
144
|
+
:io => $stdout,
|
189
145
|
}
|
190
146
|
orig_args = args.dup
|
191
147
|
|
@@ -209,6 +165,10 @@ module Minitest
|
|
209
165
|
options[:verbose] = true
|
210
166
|
end
|
211
167
|
|
168
|
+
opts.on "-q", "--quiet", "Quiet. Show no progress processing files." do
|
169
|
+
options[:quiet] = true
|
170
|
+
end
|
171
|
+
|
212
172
|
opts.on "--show-skips", "Show skipped at the end of run." do
|
213
173
|
options[:show_skips] = true
|
214
174
|
end
|
@@ -225,13 +185,37 @@ module Minitest
|
|
225
185
|
options[:skip] = s.chars.to_a
|
226
186
|
end
|
227
187
|
|
188
|
+
ruby27plus = ::Warning.respond_to? :[]=
|
189
|
+
|
190
|
+
opts.on "-W[error]", String, "Turn Ruby warnings into errors" do |s|
|
191
|
+
options[:Werror] = true
|
192
|
+
case s
|
193
|
+
when "error", "all", nil then
|
194
|
+
require "minitest/error_on_warning"
|
195
|
+
$VERBOSE = true
|
196
|
+
::Warning[:deprecated] = true if ruby27plus
|
197
|
+
else
|
198
|
+
::Warning[s.to_sym] = true if ruby27plus # check validity of category
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
228
202
|
unless extensions.empty?
|
229
203
|
opts.separator ""
|
230
|
-
opts.separator "Known extensions: #{extensions.join
|
231
|
-
|
232
|
-
extensions.each do |
|
233
|
-
|
234
|
-
|
204
|
+
opts.separator "Known extensions: #{extensions.join ", "}"
|
205
|
+
|
206
|
+
extensions.each do |mod_or_meth|
|
207
|
+
case mod_or_meth
|
208
|
+
when Symbol, String then
|
209
|
+
meth = mod_or_meth
|
210
|
+
msg = "plugin_#{meth}_options"
|
211
|
+
send msg, opts, options if respond_to? msg
|
212
|
+
when Module
|
213
|
+
recv = mod_or_meth
|
214
|
+
next unless recv.respond_to? :minitest_plugin_options
|
215
|
+
recv.minitest_plugin_options opts, options
|
216
|
+
else
|
217
|
+
raise ArgumentError, "plugin is %p, but it must be a symbol, string or module" % [mod_or_meth]
|
218
|
+
end
|
235
219
|
end
|
236
220
|
end
|
237
221
|
|
@@ -255,12 +239,99 @@ module Minitest
|
|
255
239
|
end
|
256
240
|
|
257
241
|
options[:args] = orig_args.map { |s|
|
258
|
-
s
|
242
|
+
s.match?(/[\s|&<>$()]/) ? s.inspect : s
|
259
243
|
}.join " "
|
260
244
|
|
261
245
|
options
|
262
246
|
end
|
263
247
|
|
248
|
+
##
|
249
|
+
# This is the top-level run method. Everything starts from here. It
|
250
|
+
# tells each Runnable sub-class to run, and each of those are
|
251
|
+
# responsible for doing whatever they do.
|
252
|
+
#
|
253
|
+
# The overall structure of a run looks like this:
|
254
|
+
#
|
255
|
+
# Minitest.autorun
|
256
|
+
# Minitest.run(args)
|
257
|
+
# Minitest.load_plugins
|
258
|
+
# Minitest.process_args
|
259
|
+
# Minitest.init_plugins
|
260
|
+
# Minitest.__run(reporter, options)
|
261
|
+
# Runnable.runnables.each
|
262
|
+
# runnable_klass.run(reporter, options)
|
263
|
+
# self.runnable_methods.each
|
264
|
+
# self.run_one_method(self, runnable_method, reporter)
|
265
|
+
# Minitest.run_one_method(klass, runnable_method)
|
266
|
+
# klass.new(runnable_method).run
|
267
|
+
|
268
|
+
def self.run args = []
|
269
|
+
self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
|
270
|
+
|
271
|
+
options = process_args args
|
272
|
+
|
273
|
+
Minitest.seed = options[:seed]
|
274
|
+
srand Minitest.seed
|
275
|
+
|
276
|
+
reporter = CompositeReporter.new
|
277
|
+
reporter << SummaryReporter.new(options[:io], options)
|
278
|
+
reporter << ProgressReporter.new(options[:io], options) unless options[:quiet]
|
279
|
+
|
280
|
+
self.reporter = reporter # this makes it available to plugins
|
281
|
+
self.init_plugins options
|
282
|
+
self.reporter = nil # runnables shouldn't depend on the reporter, ever
|
283
|
+
|
284
|
+
self.parallel_executor.start if parallel_executor.respond_to? :start
|
285
|
+
reporter.start
|
286
|
+
begin
|
287
|
+
__run reporter, options
|
288
|
+
rescue Interrupt
|
289
|
+
warn "Interrupted. Exiting..."
|
290
|
+
end
|
291
|
+
self.parallel_executor.shutdown
|
292
|
+
|
293
|
+
# might have been removed/replaced during init_plugins:
|
294
|
+
summary = reporter.reporters.grep(SummaryReporter).first
|
295
|
+
|
296
|
+
reporter.report
|
297
|
+
|
298
|
+
return empty_run! options if summary && summary.count == 0
|
299
|
+
reporter.passed?
|
300
|
+
end
|
301
|
+
|
302
|
+
def self.empty_run! options # :nodoc:
|
303
|
+
filter = options[:filter]
|
304
|
+
return true unless filter # no filter, but nothing ran == success
|
305
|
+
|
306
|
+
warn "Nothing ran for filter: %s" % [filter]
|
307
|
+
|
308
|
+
require "did_you_mean" # soft dependency, punt if it doesn't load
|
309
|
+
|
310
|
+
ms = Runnable.runnables.flat_map(&:runnable_methods)
|
311
|
+
cs = DidYouMean::SpellChecker.new(dictionary: ms).correct filter
|
312
|
+
|
313
|
+
warn DidYouMean::Formatter.message_for cs unless cs.empty?
|
314
|
+
rescue LoadError
|
315
|
+
# do nothing
|
316
|
+
end
|
317
|
+
|
318
|
+
##
|
319
|
+
# Internal run method. Responsible for telling all Runnable
|
320
|
+
# sub-classes to run.
|
321
|
+
|
322
|
+
def self.__run reporter, options
|
323
|
+
suites = Runnable.runnables.shuffle
|
324
|
+
parallel, serial = suites.partition { |s| s.test_order == :parallel }
|
325
|
+
|
326
|
+
# If we run the parallel tests before the serial tests, the parallel tests
|
327
|
+
# could run in parallel with the serial tests. This would be bad because
|
328
|
+
# the serial tests won't lock around Reporter#record. Run the serial tests
|
329
|
+
# first, so that after they complete, the parallel tests will lock when
|
330
|
+
# recording results.
|
331
|
+
serial.map { |suite| suite.run reporter, options } +
|
332
|
+
parallel.map { |suite| suite.run reporter, options }
|
333
|
+
end
|
334
|
+
|
264
335
|
def self.filter_backtrace bt # :nodoc:
|
265
336
|
result = backtrace_filter.filter bt
|
266
337
|
result = bt.dup if result.empty?
|
@@ -331,24 +402,34 @@ module Minitest
|
|
331
402
|
# reporter to record.
|
332
403
|
|
333
404
|
def self.run reporter, options = {}
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
filtered_methods = self.runnable_methods.find_all { |m|
|
338
|
-
filter === m || filter === "#{self}##{m}"
|
339
|
-
}
|
405
|
+
pos = options[:filter]
|
406
|
+
neg = options[:exclude]
|
340
407
|
|
341
|
-
|
342
|
-
|
408
|
+
pos = Regexp.new $1 if pos.kind_of?(String) && pos =~ %r%/(.*)/%
|
409
|
+
neg = Regexp.new $1 if neg.kind_of?(String) && neg =~ %r%/(.*)/%
|
343
410
|
|
344
|
-
filtered_methods
|
345
|
-
|
346
|
-
|
411
|
+
filtered_methods = self.runnable_methods
|
412
|
+
.select { |m| !pos || pos === m || pos === "#{self}##{m}" }
|
413
|
+
.reject { |m| neg && (neg === m || neg === "#{self}##{m}") }
|
347
414
|
|
348
415
|
return if filtered_methods.empty?
|
349
416
|
|
417
|
+
t0 = name = nil
|
418
|
+
|
419
|
+
@_info_handler = lambda do
|
420
|
+
unless reporter.passed? then
|
421
|
+
warn "Current results:"
|
422
|
+
warn reporter.reporters.grep(SummaryReporter).first
|
423
|
+
end
|
424
|
+
|
425
|
+
warn "Current: %s#%s %.2fs" % [self, name, Minitest.clock_time - t0]
|
426
|
+
end
|
427
|
+
|
350
428
|
with_info_handler reporter do
|
351
429
|
filtered_methods.each do |method_name|
|
430
|
+
name = method_name
|
431
|
+
t0 = Minitest.clock_time
|
432
|
+
|
352
433
|
run_one_method self, method_name, reporter
|
353
434
|
end
|
354
435
|
end
|
@@ -365,17 +446,16 @@ module Minitest
|
|
365
446
|
reporter.record Minitest.run_one_method(klass, method_name)
|
366
447
|
end
|
367
448
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
warn "Current results:"
|
372
|
-
warn ""
|
373
|
-
warn reporter.reporters.first
|
374
|
-
warn ""
|
375
|
-
end
|
376
|
-
end
|
449
|
+
##
|
450
|
+
# Defines the order to run tests (:random by default). Override
|
451
|
+
# this or use a convenience method to change it for your tests.
|
377
452
|
|
378
|
-
|
453
|
+
def self.test_order
|
454
|
+
:random
|
455
|
+
end
|
456
|
+
|
457
|
+
def self.with_info_handler reporter, &block # :nodoc:
|
458
|
+
on_signal ::Minitest.info_signal, @_info_handler, &block
|
379
459
|
end
|
380
460
|
|
381
461
|
SIGNALS = Signal.list # :nodoc:
|
@@ -413,7 +493,7 @@ module Minitest
|
|
413
493
|
def marshal_dump # :nodoc:
|
414
494
|
unless @@marshal_dump_warned then
|
415
495
|
warn ["Minitest::Runnable#marshal_dump is deprecated.",
|
416
|
-
"You might be violating internals. From", caller.first].join " "
|
496
|
+
"You might be violating internals. From", caller(1..1).first].join " "
|
417
497
|
@@marshal_dump_warned = true
|
418
498
|
end
|
419
499
|
|
@@ -432,6 +512,31 @@ module Minitest
|
|
432
512
|
self.name = name
|
433
513
|
self.failures = []
|
434
514
|
self.assertions = 0
|
515
|
+
# lazy initializer for metadata
|
516
|
+
end
|
517
|
+
|
518
|
+
##
|
519
|
+
# Metadata you attach to the test results that get sent to the reporter.
|
520
|
+
#
|
521
|
+
# Lazily initializes to a hash, to keep memory down.
|
522
|
+
#
|
523
|
+
# NOTE: this data *must* be plain (read: marshal-able) data!
|
524
|
+
# Hashes! Arrays! Strings!
|
525
|
+
|
526
|
+
def metadata
|
527
|
+
@metadata ||= {}
|
528
|
+
end
|
529
|
+
|
530
|
+
##
|
531
|
+
# Sets metadata, mainly used for +Result.from+.
|
532
|
+
|
533
|
+
attr_writer :metadata
|
534
|
+
|
535
|
+
##
|
536
|
+
# Returns true if metadata exists.
|
537
|
+
|
538
|
+
def metadata?
|
539
|
+
defined? @metadata
|
435
540
|
end
|
436
541
|
|
437
542
|
##
|
@@ -483,12 +588,14 @@ module Minitest
|
|
483
588
|
not self.failure
|
484
589
|
end
|
485
590
|
|
591
|
+
BASE_DIR = "#{Dir.pwd}/" # :nodoc:
|
592
|
+
|
486
593
|
##
|
487
594
|
# The location identifier of this test. Depends on a method
|
488
595
|
# existing called class_name.
|
489
596
|
|
490
597
|
def location
|
491
|
-
loc = " [#{self.failure.location}]" unless passed? or error?
|
598
|
+
loc = " [#{self.failure.location.delete_prefix BASE_DIR}]" unless passed? or error?
|
492
599
|
"#{self.class_name}##{self.name}#{loc}"
|
493
600
|
end
|
494
601
|
|
@@ -514,7 +621,7 @@ module Minitest
|
|
514
621
|
# Did this run error?
|
515
622
|
|
516
623
|
def error?
|
517
|
-
self.failures.any?
|
624
|
+
self.failures.any? UnexpectedError
|
518
625
|
end
|
519
626
|
end
|
520
627
|
|
@@ -552,6 +659,7 @@ module Minitest
|
|
552
659
|
r.assertions = o.assertions
|
553
660
|
r.failures = o.failures.dup
|
554
661
|
r.time = o.time
|
662
|
+
r.metadata = o.metadata if o.metadata?
|
555
663
|
|
556
664
|
r.source_location = o.method(o.name).source_location rescue ["unknown", -1]
|
557
665
|
|
@@ -576,7 +684,10 @@ module Minitest
|
|
576
684
|
# you want. Go nuts.
|
577
685
|
|
578
686
|
class AbstractReporter
|
579
|
-
|
687
|
+
|
688
|
+
def initialize # :nodoc:
|
689
|
+
@mutex = Mutex.new
|
690
|
+
end
|
580
691
|
|
581
692
|
##
|
582
693
|
# Starts reporting on the run.
|
@@ -612,6 +723,10 @@ module Minitest
|
|
612
723
|
def passed?
|
613
724
|
true
|
614
725
|
end
|
726
|
+
|
727
|
+
def synchronize &block # :nodoc:
|
728
|
+
@mutex.synchronize(&block)
|
729
|
+
end
|
615
730
|
end
|
616
731
|
|
617
732
|
class Reporter < AbstractReporter # :nodoc:
|
@@ -641,11 +756,11 @@ module Minitest
|
|
641
756
|
# own.
|
642
757
|
|
643
758
|
class ProgressReporter < Reporter
|
644
|
-
def prerecord klass, name
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
759
|
+
def prerecord klass, name # :nodoc:
|
760
|
+
return unless options[:verbose]
|
761
|
+
|
762
|
+
io.print "%s#%s = " % [klass.name, name]
|
763
|
+
io.flush
|
649
764
|
end
|
650
765
|
|
651
766
|
def record result # :nodoc:
|
@@ -715,6 +830,11 @@ module Minitest
|
|
715
830
|
|
716
831
|
attr_accessor :errors
|
717
832
|
|
833
|
+
##
|
834
|
+
# Total number of tests that warned.
|
835
|
+
|
836
|
+
attr_accessor :warnings
|
837
|
+
|
718
838
|
##
|
719
839
|
# Total number of tests that where skipped.
|
720
840
|
|
@@ -730,6 +850,7 @@ module Minitest
|
|
730
850
|
self.total_time = nil
|
731
851
|
self.failures = nil
|
732
852
|
self.errors = nil
|
853
|
+
self.warnings = nil
|
733
854
|
self.skips = nil
|
734
855
|
end
|
735
856
|
|
@@ -758,6 +879,7 @@ module Minitest
|
|
758
879
|
self.total_time = Minitest.clock_time - start_time
|
759
880
|
self.failures = aggregate[Assertion].size
|
760
881
|
self.errors = aggregate[UnexpectedError].size
|
882
|
+
self.warnings = aggregate[UnexpectedWarning].size
|
761
883
|
self.skips = aggregate[Skip].size
|
762
884
|
end
|
763
885
|
end
|
@@ -772,10 +894,8 @@ module Minitest
|
|
772
894
|
# own.
|
773
895
|
|
774
896
|
class SummaryReporter < StatisticsReporter
|
775
|
-
# :
|
776
|
-
attr_accessor :
|
777
|
-
attr_accessor :old_sync
|
778
|
-
# :startdoc:
|
897
|
+
attr_accessor :sync # :nodoc:
|
898
|
+
attr_accessor :old_sync # :nodoc:
|
779
899
|
|
780
900
|
def start # :nodoc:
|
781
901
|
super
|
@@ -785,7 +905,7 @@ module Minitest
|
|
785
905
|
io.puts "# Running:"
|
786
906
|
io.puts
|
787
907
|
|
788
|
-
self.sync = io.respond_to? :"sync="
|
908
|
+
self.sync = io.respond_to? :"sync="
|
789
909
|
self.old_sync, io.sync = io.sync, true if self.sync
|
790
910
|
end
|
791
911
|
|
@@ -823,26 +943,22 @@ module Minitest
|
|
823
943
|
end
|
824
944
|
|
825
945
|
def to_s # :nodoc:
|
826
|
-
aggregated_results(StringIO.new(
|
946
|
+
aggregated_results(StringIO.new("".b)).string
|
827
947
|
end
|
828
948
|
|
829
949
|
def summary # :nodoc:
|
830
|
-
extra =
|
950
|
+
extra = []
|
951
|
+
|
952
|
+
extra << ", %d warnings" % [warnings] if options[:Werror]
|
831
953
|
|
832
|
-
extra
|
954
|
+
extra << "\n\nYou have skipped tests. Run with --verbose for details." if
|
833
955
|
results.any?(&:skipped?) unless
|
834
|
-
options[:verbose]
|
956
|
+
options[:verbose] or
|
957
|
+
options[:show_skips] or
|
958
|
+
ENV["MT_NO_SKIP_MSG"]
|
835
959
|
|
836
960
|
"%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
|
837
|
-
[count, assertions, failures, errors, skips, extra]
|
838
|
-
end
|
839
|
-
|
840
|
-
private
|
841
|
-
|
842
|
-
if '<3'.respond_to? :b
|
843
|
-
def binary_string; ''.b; end
|
844
|
-
else
|
845
|
-
def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end
|
961
|
+
[count, assertions, failures, errors, skips, extra.join]
|
846
962
|
end
|
847
963
|
end
|
848
964
|
|
@@ -901,6 +1017,8 @@ module Minitest
|
|
901
1017
|
# Represents run failures.
|
902
1018
|
|
903
1019
|
class Assertion < Exception
|
1020
|
+
RE = /in [`'](?:[^']+[#.])?(?:assert|refute|flunk|pass|fail|raise|must|wont)/ # :nodoc:
|
1021
|
+
|
904
1022
|
def error # :nodoc:
|
905
1023
|
self
|
906
1024
|
end
|
@@ -909,12 +1027,11 @@ module Minitest
|
|
909
1027
|
# Where was this run before an assertion was raised?
|
910
1028
|
|
911
1029
|
def location
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
last_before_assertion.sub(/:in .*$/, "")
|
1030
|
+
bt = Minitest.filter_backtrace self.backtrace
|
1031
|
+
idx = bt.rindex { |s| s.match? RE } || -1 # fall back to first item
|
1032
|
+
loc = bt[idx+1] || bt.last || "unknown:-1"
|
1033
|
+
|
1034
|
+
loc.sub(/:in .*$/, "")
|
918
1035
|
end
|
919
1036
|
|
920
1037
|
def result_code # :nodoc:
|
@@ -939,11 +1056,21 @@ module Minitest
|
|
939
1056
|
# Assertion wrapping an unexpected error that was raised during a run.
|
940
1057
|
|
941
1058
|
class UnexpectedError < Assertion
|
1059
|
+
include Minitest::Compress
|
1060
|
+
|
942
1061
|
# TODO: figure out how to use `cause` instead
|
943
1062
|
attr_accessor :error # :nodoc:
|
944
1063
|
|
945
1064
|
def initialize error # :nodoc:
|
946
1065
|
super "Unexpected exception"
|
1066
|
+
|
1067
|
+
if SystemStackError === error then
|
1068
|
+
bt = error.backtrace
|
1069
|
+
new_bt = compress bt
|
1070
|
+
error = error.exception "#{bt.size} -> #{new_bt.size}"
|
1071
|
+
error.set_backtrace new_bt
|
1072
|
+
end
|
1073
|
+
|
947
1074
|
self.error = error
|
948
1075
|
end
|
949
1076
|
|
@@ -951,8 +1078,11 @@ module Minitest
|
|
951
1078
|
self.error.backtrace
|
952
1079
|
end
|
953
1080
|
|
1081
|
+
BASE_RE = %r%#{Dir.pwd}/% # :nodoc:
|
1082
|
+
|
954
1083
|
def message # :nodoc:
|
955
|
-
bt = Minitest.filter_backtrace(self.backtrace).join
|
1084
|
+
bt = Minitest.filter_backtrace(self.backtrace).join("\n ")
|
1085
|
+
.gsub(BASE_RE, "")
|
956
1086
|
"#{self.error.class}: #{self.error.message}\n #{bt}"
|
957
1087
|
end
|
958
1088
|
|
@@ -961,6 +1091,15 @@ module Minitest
|
|
961
1091
|
end
|
962
1092
|
end
|
963
1093
|
|
1094
|
+
##
|
1095
|
+
# Assertion raised on warning when running in -Werror mode.
|
1096
|
+
|
1097
|
+
class UnexpectedWarning < Assertion
|
1098
|
+
def result_label # :nodoc:
|
1099
|
+
"Warning"
|
1100
|
+
end
|
1101
|
+
end
|
1102
|
+
|
964
1103
|
##
|
965
1104
|
# Provides a simple set of guards that you can use in your tests
|
966
1105
|
# to skip execution if it is not applicable. These methods are
|
@@ -990,7 +1129,7 @@ module Minitest
|
|
990
1129
|
|
991
1130
|
def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
992
1131
|
where = Minitest.filter_backtrace(caller).first
|
993
|
-
where = where.split(
|
1132
|
+
where = where.split(":in ", 2).first # clean up noise
|
994
1133
|
warn "DEPRECATED: `maglev?` called from #{where}. This will fail in Minitest 6."
|
995
1134
|
"maglev" == platform
|
996
1135
|
end
|
@@ -999,14 +1138,14 @@ module Minitest
|
|
999
1138
|
# Is this running on mri?
|
1000
1139
|
|
1001
1140
|
def mri? platform = RUBY_DESCRIPTION
|
1002
|
-
|
1141
|
+
platform.start_with? "ruby"
|
1003
1142
|
end
|
1004
1143
|
|
1005
1144
|
##
|
1006
1145
|
# Is this running on macOS?
|
1007
1146
|
|
1008
1147
|
def osx? platform = RUBY_PLATFORM
|
1009
|
-
|
1148
|
+
platform.include? "darwin"
|
1010
1149
|
end
|
1011
1150
|
|
1012
1151
|
##
|
@@ -1014,7 +1153,7 @@ module Minitest
|
|
1014
1153
|
|
1015
1154
|
def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
1016
1155
|
where = Minitest.filter_backtrace(caller).first
|
1017
|
-
where = where.split(
|
1156
|
+
where = where.split(":in ", 2).first # clean up noise
|
1018
1157
|
warn "DEPRECATED: `rubinius?` called from #{where}. This will fail in Minitest 6."
|
1019
1158
|
"rbx" == platform
|
1020
1159
|
end
|
@@ -1023,7 +1162,7 @@ module Minitest
|
|
1023
1162
|
# Is this running on windows?
|
1024
1163
|
|
1025
1164
|
def windows? platform = RUBY_PLATFORM
|
1026
|
-
/mswin|mingw
|
1165
|
+
/mswin|mingw/.match? platform
|
1027
1166
|
end
|
1028
1167
|
end
|
1029
1168
|
|
@@ -1034,7 +1173,16 @@ module Minitest
|
|
1034
1173
|
|
1035
1174
|
class BacktraceFilter
|
1036
1175
|
|
1037
|
-
MT_RE = %r%lib/minitest%
|
1176
|
+
MT_RE = %r%lib/minitest|internal:warning% # :nodoc:
|
1177
|
+
|
1178
|
+
##
|
1179
|
+
# The regular expression to use to filter backtraces. Defaults to +MT_RE+.
|
1180
|
+
|
1181
|
+
attr_accessor :regexp
|
1182
|
+
|
1183
|
+
def initialize regexp = MT_RE # :nodoc:
|
1184
|
+
self.regexp = regexp
|
1185
|
+
end
|
1038
1186
|
|
1039
1187
|
##
|
1040
1188
|
# Filter +bt+ to something useful. Returns the whole thing if
|
@@ -1045,9 +1193,9 @@ module Minitest
|
|
1045
1193
|
|
1046
1194
|
return bt.dup if $DEBUG || ENV["MT_DEBUG"]
|
1047
1195
|
|
1048
|
-
new_bt = bt.take_while { |line| line
|
1049
|
-
new_bt = bt.select { |line| line
|
1050
|
-
new_bt = bt.dup
|
1196
|
+
new_bt = bt.take_while { |line| !regexp.match? line.to_s }
|
1197
|
+
new_bt = bt.select { |line| !regexp.match? line.to_s } if new_bt.empty?
|
1198
|
+
new_bt = bt.dup if new_bt.empty?
|
1051
1199
|
|
1052
1200
|
new_bt
|
1053
1201
|
end
|