minitest 5.12.0 → 5.22.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.rdoc +262 -5
- data/Manifest.txt +3 -0
- data/README.rdoc +90 -17
- data/Rakefile +5 -16
- data/lib/hoe/minitest.rb +0 -4
- data/lib/minitest/assertions.rb +171 -37
- data/lib/minitest/benchmark.rb +7 -7
- data/lib/minitest/compress.rb +94 -0
- data/lib/minitest/expectations.rb +72 -35
- data/lib/minitest/mock.rb +123 -34
- data/lib/minitest/pride_plugin.rb +1 -1
- data/lib/minitest/spec.rb +24 -10
- data/lib/minitest/test.rb +44 -16
- data/lib/minitest/test_task.rb +301 -0
- data/lib/minitest/unit.rb +5 -8
- data/lib/minitest.rb +245 -70
- data/test/minitest/metametameta.rb +45 -11
- data/test/minitest/test_minitest_assertions.rb +357 -29
- data/test/minitest/test_minitest_benchmark.rb +2 -2
- data/test/minitest/test_minitest_mock.rb +287 -15
- data/test/minitest/test_minitest_reporter.rb +158 -17
- data/test/minitest/test_minitest_spec.rb +184 -59
- data/test/minitest/test_minitest_test.rb +362 -42
- data/test/minitest/test_minitest_test_task.rb +46 -0
- data.tar.gz.sig +2 -2
- metadata +28 -19
- metadata.gz.sig +0 -0
data/lib/minitest.rb
CHANGED
@@ -1,64 +1,84 @@
|
|
1
1
|
require "optparse"
|
2
|
-
require "thread"
|
3
|
-
require "mutex_m"
|
4
|
-
require "minitest/parallel"
|
5
2
|
require "stringio"
|
3
|
+
require "etc"
|
4
|
+
|
5
|
+
require_relative "minitest/parallel"
|
6
|
+
require_relative "minitest/compress"
|
6
7
|
|
7
8
|
##
|
8
9
|
# :include: README.rdoc
|
9
10
|
|
10
11
|
module Minitest
|
11
|
-
VERSION = "5.
|
12
|
-
ENCS = "".respond_to? :encoding # :nodoc:
|
12
|
+
VERSION = "5.22.2" # :nodoc:
|
13
13
|
|
14
14
|
@@installed_at_exit ||= false
|
15
15
|
@@after_run = []
|
16
16
|
@extensions = []
|
17
17
|
|
18
|
-
|
18
|
+
def self.cattr_accessor name # :nodoc:
|
19
|
+
(class << self; self; end).attr_accessor name
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# The random seed used for this run. This is used to srand at the
|
24
|
+
# start of the run and between each +Runnable.run+.
|
25
|
+
#
|
26
|
+
# Set via Minitest.run after processing args.
|
27
|
+
|
28
|
+
cattr_accessor :seed
|
19
29
|
|
20
30
|
##
|
21
31
|
# Parallel test executor
|
22
32
|
|
23
|
-
|
33
|
+
cattr_accessor :parallel_executor
|
34
|
+
|
35
|
+
warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"] && ENV["N"].to_i > 0
|
36
|
+
n_threads = (ENV["MT_CPU"] || ENV["N"] || Etc.nprocessors).to_i
|
24
37
|
|
25
|
-
warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"]
|
26
|
-
n_threads = (ENV["MT_CPU"] || ENV["N"] || 2).to_i
|
27
38
|
self.parallel_executor = Parallel::Executor.new n_threads
|
28
39
|
|
29
40
|
##
|
30
41
|
# Filter object for backtraces.
|
31
42
|
|
32
|
-
|
43
|
+
cattr_accessor :backtrace_filter
|
33
44
|
|
34
45
|
##
|
35
46
|
# Reporter object to be used for all runs.
|
36
47
|
#
|
37
48
|
# NOTE: This accessor is only available during setup, not during runs.
|
38
49
|
|
39
|
-
|
50
|
+
cattr_accessor :reporter
|
40
51
|
|
41
52
|
##
|
42
53
|
# Names of known extension plugins.
|
43
54
|
|
44
|
-
|
55
|
+
cattr_accessor :extensions
|
45
56
|
|
46
57
|
##
|
47
58
|
# The signal to use for dumping information to STDERR. Defaults to "INFO".
|
48
59
|
|
49
|
-
|
60
|
+
cattr_accessor :info_signal
|
50
61
|
self.info_signal = "INFO"
|
51
62
|
|
63
|
+
cattr_accessor :allow_fork
|
64
|
+
self.allow_fork = false
|
65
|
+
|
52
66
|
##
|
53
67
|
# Registers Minitest to run at process exit
|
54
68
|
|
55
69
|
def self.autorun
|
70
|
+
if Object.const_defined?(:Warning) && Warning.respond_to?(:[]=)
|
71
|
+
Warning[:deprecated] = true
|
72
|
+
end
|
73
|
+
|
56
74
|
at_exit {
|
57
75
|
next if $! and not ($!.kind_of? SystemExit and $!.success?)
|
58
76
|
|
59
77
|
exit_code = nil
|
60
78
|
|
79
|
+
pid = Process.pid
|
61
80
|
at_exit {
|
81
|
+
next if !Minitest.allow_fork && Process.pid != pid
|
62
82
|
@@after_run.reverse_each(&:call)
|
63
83
|
exit exit_code || false
|
64
84
|
}
|
@@ -114,7 +134,7 @@ module Minitest
|
|
114
134
|
# Minitest.run(args)
|
115
135
|
# Minitest.__run(reporter, options)
|
116
136
|
# Runnable.runnables.each
|
117
|
-
#
|
137
|
+
# runnable_klass.run(reporter, options)
|
118
138
|
# self.runnable_methods.each
|
119
139
|
# self.run_one_method(self, runnable_method, reporter)
|
120
140
|
# Minitest.run_one_method(klass, runnable_method)
|
@@ -125,9 +145,12 @@ module Minitest
|
|
125
145
|
|
126
146
|
options = process_args args
|
127
147
|
|
148
|
+
Minitest.seed = options[:seed]
|
149
|
+
srand Minitest.seed
|
150
|
+
|
128
151
|
reporter = CompositeReporter.new
|
129
152
|
reporter << SummaryReporter.new(options[:io], options)
|
130
|
-
reporter << ProgressReporter.new(options[:io], options)
|
153
|
+
reporter << ProgressReporter.new(options[:io], options) unless options[:quiet]
|
131
154
|
|
132
155
|
self.reporter = reporter # this makes it available to plugins
|
133
156
|
self.init_plugins options
|
@@ -141,17 +164,38 @@ module Minitest
|
|
141
164
|
warn "Interrupted. Exiting..."
|
142
165
|
end
|
143
166
|
self.parallel_executor.shutdown
|
167
|
+
|
168
|
+
# might have been removed/replaced during init_plugins:
|
169
|
+
summary = reporter.reporters.grep(SummaryReporter).first
|
170
|
+
return empty_run! options if summary && summary.count == 0
|
171
|
+
|
144
172
|
reporter.report
|
145
173
|
|
146
174
|
reporter.passed?
|
147
175
|
end
|
148
176
|
|
177
|
+
def self.empty_run! options # :nodoc:
|
178
|
+
filter = options[:filter]
|
179
|
+
return true unless filter # no filter, but nothing ran == success
|
180
|
+
|
181
|
+
warn "Nothing ran for filter: %s" % [filter]
|
182
|
+
|
183
|
+
require "did_you_mean" # soft dependency, punt if it doesn't load
|
184
|
+
|
185
|
+
ms = Runnable.runnables.flat_map(&:runnable_methods)
|
186
|
+
cs = DidYouMean::SpellChecker.new(dictionary: ms).correct filter
|
187
|
+
|
188
|
+
warn DidYouMean::Formatter.message_for cs unless cs.empty?
|
189
|
+
rescue LoadError
|
190
|
+
# do nothing
|
191
|
+
end
|
192
|
+
|
149
193
|
##
|
150
194
|
# Internal run method. Responsible for telling all Runnable
|
151
195
|
# sub-classes to run.
|
152
196
|
|
153
197
|
def self.__run reporter, options
|
154
|
-
suites = Runnable.runnables.
|
198
|
+
suites = Runnable.runnables.shuffle
|
155
199
|
parallel, serial = suites.partition { |s| s.test_order == :parallel }
|
156
200
|
|
157
201
|
# If we run the parallel tests before the serial tests, the parallel tests
|
@@ -189,6 +233,14 @@ module Minitest
|
|
189
233
|
options[:verbose] = true
|
190
234
|
end
|
191
235
|
|
236
|
+
opts.on "-q", "--quiet", "Quiet. Show no progress processing files." do
|
237
|
+
options[:quiet] = true
|
238
|
+
end
|
239
|
+
|
240
|
+
opts.on "--show-skips", "Show skipped at the end of run." do
|
241
|
+
options[:show_skips] = true
|
242
|
+
end
|
243
|
+
|
192
244
|
opts.on "-n", "--name PATTERN", "Filter run on /regexp/ or string." do |a|
|
193
245
|
options[:filter] = a
|
194
246
|
end
|
@@ -197,6 +249,10 @@ module Minitest
|
|
197
249
|
options[:exclude] = a
|
198
250
|
end
|
199
251
|
|
252
|
+
opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s|
|
253
|
+
options[:skip] = s.chars.to_a
|
254
|
+
end
|
255
|
+
|
200
256
|
unless extensions.empty?
|
201
257
|
opts.separator ""
|
202
258
|
opts.separator "Known extensions: #{extensions.join(", ")}"
|
@@ -226,8 +282,6 @@ module Minitest
|
|
226
282
|
orig_args << "--seed" << options[:seed].to_s
|
227
283
|
end
|
228
284
|
|
229
|
-
srand options[:seed]
|
230
|
-
|
231
285
|
options[:args] = orig_args.map { |s|
|
232
286
|
s =~ /[\s|&<>$()]/ ? s.inspect : s
|
233
287
|
}.join " "
|
@@ -236,7 +290,9 @@ module Minitest
|
|
236
290
|
end
|
237
291
|
|
238
292
|
def self.filter_backtrace bt # :nodoc:
|
239
|
-
backtrace_filter.filter bt
|
293
|
+
result = backtrace_filter.filter bt
|
294
|
+
result = bt.dup if result.empty?
|
295
|
+
result
|
240
296
|
end
|
241
297
|
|
242
298
|
##
|
@@ -303,19 +359,15 @@ module Minitest
|
|
303
359
|
# reporter to record.
|
304
360
|
|
305
361
|
def self.run reporter, options = {}
|
306
|
-
|
307
|
-
|
362
|
+
pos = options[:filter]
|
363
|
+
neg = options[:exclude]
|
308
364
|
|
309
|
-
|
310
|
-
|
311
|
-
}
|
312
|
-
|
313
|
-
exclude = options[:exclude]
|
314
|
-
exclude = Regexp.new $1 if exclude =~ %r%/(.*)/%
|
365
|
+
pos = Regexp.new $1 if pos.is_a?(String) && pos =~ %r%/(.*)/%
|
366
|
+
neg = Regexp.new $1 if neg.is_a?(String) && neg =~ %r%/(.*)/%
|
315
367
|
|
316
|
-
filtered_methods
|
317
|
-
|
318
|
-
|
368
|
+
filtered_methods = self.runnable_methods
|
369
|
+
.select { |m| !pos || pos === m || pos === "#{self}##{m}" }
|
370
|
+
.reject { |m| neg && (neg === m || neg === "#{self}##{m}") }
|
319
371
|
|
320
372
|
return if filtered_methods.empty?
|
321
373
|
|
@@ -337,6 +389,14 @@ module Minitest
|
|
337
389
|
reporter.record Minitest.run_one_method(klass, method_name)
|
338
390
|
end
|
339
391
|
|
392
|
+
##
|
393
|
+
# Defines the order to run tests (:random by default). Override
|
394
|
+
# this or use a convenience method to change it for your tests.
|
395
|
+
|
396
|
+
def self.test_order
|
397
|
+
:random
|
398
|
+
end
|
399
|
+
|
340
400
|
def self.with_info_handler reporter, &block # :nodoc:
|
341
401
|
handler = lambda do
|
342
402
|
unless reporter.passed? then
|
@@ -404,6 +464,31 @@ module Minitest
|
|
404
464
|
self.name = name
|
405
465
|
self.failures = []
|
406
466
|
self.assertions = 0
|
467
|
+
# lazy initializer for metadata
|
468
|
+
end
|
469
|
+
|
470
|
+
##
|
471
|
+
# Metadata you attach to the test results that get sent to the reporter.
|
472
|
+
#
|
473
|
+
# Lazily initializes to a hash, to keep memory down.
|
474
|
+
#
|
475
|
+
# NOTE: this data *must* be plain (read: marshal-able) data!
|
476
|
+
# Hashes! Arrays! Strings!
|
477
|
+
|
478
|
+
def metadata
|
479
|
+
@metadata ||= {}
|
480
|
+
end
|
481
|
+
|
482
|
+
##
|
483
|
+
# Sets metadata, mainly used for +Result.from+.
|
484
|
+
|
485
|
+
attr_writer :metadata
|
486
|
+
|
487
|
+
##
|
488
|
+
# Returns true if metadata exists.
|
489
|
+
|
490
|
+
def metadata?
|
491
|
+
defined? @metadata
|
407
492
|
end
|
408
493
|
|
409
494
|
##
|
@@ -425,7 +510,8 @@ module Minitest
|
|
425
510
|
|
426
511
|
##
|
427
512
|
# Returns a single character string to print based on the result
|
428
|
-
# of the run.
|
513
|
+
# of the run. One of <tt>"."</tt>, <tt>"F"</tt>,
|
514
|
+
# <tt>"E"</tt> or <tt>"S"</tt>.
|
429
515
|
|
430
516
|
def result_code
|
431
517
|
raise NotImplementedError, "subclass responsibility"
|
@@ -454,12 +540,14 @@ module Minitest
|
|
454
540
|
not self.failure
|
455
541
|
end
|
456
542
|
|
543
|
+
BASE_DIR = "#{Dir.pwd}/" # :nodoc:
|
544
|
+
|
457
545
|
##
|
458
546
|
# The location identifier of this test. Depends on a method
|
459
547
|
# existing called class_name.
|
460
548
|
|
461
549
|
def location
|
462
|
-
loc = " [#{self.failure.location}]" unless passed? or error?
|
550
|
+
loc = " [#{self.failure.location.delete_prefix BASE_DIR}]" unless passed? or error?
|
463
551
|
"#{self.class_name}##{self.name}#{loc}"
|
464
552
|
end
|
465
553
|
|
@@ -523,6 +611,7 @@ module Minitest
|
|
523
611
|
r.assertions = o.assertions
|
524
612
|
r.failures = o.failures.dup
|
525
613
|
r.time = o.time
|
614
|
+
r.metadata = o.metadata if o.metadata?
|
526
615
|
|
527
616
|
r.source_location = o.method(o.name).source_location rescue ["unknown", -1]
|
528
617
|
|
@@ -547,7 +636,10 @@ module Minitest
|
|
547
636
|
# you want. Go nuts.
|
548
637
|
|
549
638
|
class AbstractReporter
|
550
|
-
|
639
|
+
|
640
|
+
def initialize # :nodoc:
|
641
|
+
@mutex = Mutex.new
|
642
|
+
end
|
551
643
|
|
552
644
|
##
|
553
645
|
# Starts reporting on the run.
|
@@ -563,8 +655,10 @@ module Minitest
|
|
563
655
|
end
|
564
656
|
|
565
657
|
##
|
566
|
-
#
|
567
|
-
# result
|
658
|
+
# Output and record the result of the test. Call
|
659
|
+
# {result#result_code}[rdoc-ref:Runnable#result_code] to get the
|
660
|
+
# result character string. Stores the result of the run if the run
|
661
|
+
# did not pass.
|
568
662
|
|
569
663
|
def record result
|
570
664
|
end
|
@@ -581,6 +675,10 @@ module Minitest
|
|
581
675
|
def passed?
|
582
676
|
true
|
583
677
|
end
|
678
|
+
|
679
|
+
def synchronize(&block) # :nodoc:
|
680
|
+
@mutex.synchronize(&block)
|
681
|
+
end
|
584
682
|
end
|
585
683
|
|
586
684
|
class Reporter < AbstractReporter # :nodoc:
|
@@ -631,18 +729,63 @@ module Minitest
|
|
631
729
|
#
|
632
730
|
# If you want to create an entirely different type of output (eg,
|
633
731
|
# CI, HTML, etc), this is the place to start.
|
732
|
+
#
|
733
|
+
# Example:
|
734
|
+
#
|
735
|
+
# class JenkinsCIReporter < StatisticsReporter
|
736
|
+
# def report
|
737
|
+
# super # Needed to calculate some statistics
|
738
|
+
#
|
739
|
+
# print "<testsuite "
|
740
|
+
# print "tests='#{count}' "
|
741
|
+
# print "failures='#{failures}' "
|
742
|
+
# # Remaining XML...
|
743
|
+
# end
|
744
|
+
# end
|
634
745
|
|
635
746
|
class StatisticsReporter < Reporter
|
636
|
-
|
747
|
+
##
|
748
|
+
# Total number of assertions.
|
749
|
+
|
637
750
|
attr_accessor :assertions
|
751
|
+
|
752
|
+
##
|
753
|
+
# Total number of test cases.
|
754
|
+
|
638
755
|
attr_accessor :count
|
756
|
+
|
757
|
+
##
|
758
|
+
# An +Array+ of test cases that failed or were skipped.
|
759
|
+
|
639
760
|
attr_accessor :results
|
761
|
+
|
762
|
+
##
|
763
|
+
# Time the test run started. If available, the monotonic clock is
|
764
|
+
# used and this is a +Float+, otherwise it's an instance of
|
765
|
+
# +Time+.
|
766
|
+
|
640
767
|
attr_accessor :start_time
|
768
|
+
|
769
|
+
##
|
770
|
+
# Test run time. If available, the monotonic clock is used and
|
771
|
+
# this is a +Float+, otherwise it's an instance of +Time+.
|
772
|
+
|
641
773
|
attr_accessor :total_time
|
774
|
+
|
775
|
+
##
|
776
|
+
# Total number of tests that failed.
|
777
|
+
|
642
778
|
attr_accessor :failures
|
779
|
+
|
780
|
+
##
|
781
|
+
# Total number of tests that erred.
|
782
|
+
|
643
783
|
attr_accessor :errors
|
784
|
+
|
785
|
+
##
|
786
|
+
# Total number of tests that where skipped.
|
787
|
+
|
644
788
|
attr_accessor :skips
|
645
|
-
# :startdoc:
|
646
789
|
|
647
790
|
def initialize io = $stdout, options = {} # :nodoc:
|
648
791
|
super
|
@@ -672,7 +815,10 @@ module Minitest
|
|
672
815
|
results << result if not result.passed? or result.skipped?
|
673
816
|
end
|
674
817
|
|
675
|
-
|
818
|
+
##
|
819
|
+
# Report on the tracked statistics.
|
820
|
+
|
821
|
+
def report
|
676
822
|
aggregate = results.group_by { |r| r.failure.class }
|
677
823
|
aggregate.default = [] # dumb. group_by should provide this
|
678
824
|
|
@@ -706,7 +852,7 @@ module Minitest
|
|
706
852
|
io.puts "# Running:"
|
707
853
|
io.puts
|
708
854
|
|
709
|
-
self.sync = io.respond_to? :"sync="
|
855
|
+
self.sync = io.respond_to? :"sync="
|
710
856
|
self.old_sync, io.sync = io.sync, true if self.sync
|
711
857
|
end
|
712
858
|
|
@@ -729,9 +875,14 @@ module Minitest
|
|
729
875
|
|
730
876
|
def aggregated_results io # :nodoc:
|
731
877
|
filtered_results = results.dup
|
732
|
-
filtered_results.reject!(&:skipped?) unless
|
878
|
+
filtered_results.reject!(&:skipped?) unless
|
879
|
+
options[:verbose] or options[:show_skips]
|
880
|
+
|
881
|
+
skip = options[:skip] || []
|
733
882
|
|
734
883
|
filtered_results.each_with_index { |result, i|
|
884
|
+
next if skip.include? result.result_code
|
885
|
+
|
735
886
|
io.puts "\n%3d) %s" % [i+1, result]
|
736
887
|
}
|
737
888
|
io.puts
|
@@ -739,26 +890,19 @@ module Minitest
|
|
739
890
|
end
|
740
891
|
|
741
892
|
def to_s # :nodoc:
|
742
|
-
aggregated_results(StringIO.new(
|
893
|
+
aggregated_results(StringIO.new(''.b)).string
|
743
894
|
end
|
744
895
|
|
745
896
|
def summary # :nodoc:
|
746
897
|
extra = ""
|
747
898
|
|
748
899
|
extra = "\n\nYou have skipped tests. Run with --verbose for details." if
|
749
|
-
results.any?(&:skipped?) unless
|
900
|
+
results.any?(&:skipped?) unless
|
901
|
+
options[:verbose] or options[:show_skips] or ENV["MT_NO_SKIP_MSG"]
|
750
902
|
|
751
903
|
"%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
|
752
904
|
[count, assertions, failures, errors, skips, extra]
|
753
905
|
end
|
754
|
-
|
755
|
-
private
|
756
|
-
|
757
|
-
if '<3'.respond_to? :b
|
758
|
-
def binary_string; ''.b; end
|
759
|
-
else
|
760
|
-
def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end
|
761
|
-
end
|
762
906
|
end
|
763
907
|
|
764
908
|
##
|
@@ -816,6 +960,8 @@ module Minitest
|
|
816
960
|
# Represents run failures.
|
817
961
|
|
818
962
|
class Assertion < Exception
|
963
|
+
RE = /in .(?:assert|refute|flunk|pass|fail|raise|must|wont)/ # :nodoc:
|
964
|
+
|
819
965
|
def error # :nodoc:
|
820
966
|
self
|
821
967
|
end
|
@@ -824,12 +970,11 @@ module Minitest
|
|
824
970
|
# Where was this run before an assertion was raised?
|
825
971
|
|
826
972
|
def location
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
last_before_assertion.sub(/:in .*$/, "")
|
973
|
+
bt = Minitest.filter_backtrace self.backtrace
|
974
|
+
idx = bt.rindex { |s| s.match? RE } || -1 # fall back to first item
|
975
|
+
loc = bt[idx+1] || bt.last || "unknown:-1"
|
976
|
+
|
977
|
+
loc.sub(/:in .*$/, "")
|
833
978
|
end
|
834
979
|
|
835
980
|
def result_code # :nodoc:
|
@@ -854,24 +999,34 @@ module Minitest
|
|
854
999
|
# Assertion wrapping an unexpected error that was raised during a run.
|
855
1000
|
|
856
1001
|
class UnexpectedError < Assertion
|
857
|
-
|
1002
|
+
include Minitest::Compress
|
858
1003
|
|
859
|
-
|
1004
|
+
# TODO: figure out how to use `cause` instead
|
1005
|
+
attr_accessor :error # :nodoc:
|
1006
|
+
|
1007
|
+
def initialize error # :nodoc:
|
860
1008
|
super "Unexpected exception"
|
861
|
-
|
1009
|
+
|
1010
|
+
if SystemStackError === error then
|
1011
|
+
bt = error.backtrace
|
1012
|
+
new_bt = compress bt
|
1013
|
+
error = error.exception "#{bt.size} -> #{new_bt.size}"
|
1014
|
+
error.set_backtrace new_bt
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
self.error = error
|
862
1018
|
end
|
863
1019
|
|
864
1020
|
def backtrace # :nodoc:
|
865
|
-
self.
|
1021
|
+
self.error.backtrace
|
866
1022
|
end
|
867
1023
|
|
868
|
-
|
869
|
-
self.exception
|
870
|
-
end
|
1024
|
+
BASE_RE = %r%#{Dir.pwd}/% # :nodoc:
|
871
1025
|
|
872
1026
|
def message # :nodoc:
|
873
|
-
bt = Minitest.filter_backtrace(self.backtrace).join
|
874
|
-
|
1027
|
+
bt = Minitest.filter_backtrace(self.backtrace).join("\n ")
|
1028
|
+
.gsub(BASE_RE, "")
|
1029
|
+
"#{self.error.class}: #{self.error.message}\n #{bt}"
|
875
1030
|
end
|
876
1031
|
|
877
1032
|
def result_label # :nodoc:
|
@@ -907,6 +1062,9 @@ module Minitest
|
|
907
1062
|
# Is this running on maglev?
|
908
1063
|
|
909
1064
|
def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
1065
|
+
where = Minitest.filter_backtrace(caller).first
|
1066
|
+
where = where.split(/:in /, 2).first # clean up noise
|
1067
|
+
warn "DEPRECATED: `maglev?` called from #{where}. This will fail in Minitest 6."
|
910
1068
|
"maglev" == platform
|
911
1069
|
end
|
912
1070
|
|
@@ -917,10 +1075,20 @@ module Minitest
|
|
917
1075
|
/^ruby/ =~ platform
|
918
1076
|
end
|
919
1077
|
|
1078
|
+
##
|
1079
|
+
# Is this running on macOS?
|
1080
|
+
|
1081
|
+
def osx? platform = RUBY_PLATFORM
|
1082
|
+
/darwin/ =~ platform
|
1083
|
+
end
|
1084
|
+
|
920
1085
|
##
|
921
1086
|
# Is this running on rubinius?
|
922
1087
|
|
923
1088
|
def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
1089
|
+
where = Minitest.filter_backtrace(caller).first
|
1090
|
+
where = where.split(/:in /, 2).first # clean up noise
|
1091
|
+
warn "DEPRECATED: `rubinius?` called from #{where}. This will fail in Minitest 6."
|
924
1092
|
"rbx" == platform
|
925
1093
|
end
|
926
1094
|
|
@@ -941,17 +1109,24 @@ module Minitest
|
|
941
1109
|
|
942
1110
|
MT_RE = %r%lib/minitest% #:nodoc:
|
943
1111
|
|
1112
|
+
attr_accessor :regexp
|
1113
|
+
|
1114
|
+
def initialize regexp = MT_RE
|
1115
|
+
self.regexp = regexp
|
1116
|
+
end
|
1117
|
+
|
944
1118
|
##
|
945
|
-
# Filter +bt+ to something useful. Returns the whole thing if
|
1119
|
+
# Filter +bt+ to something useful. Returns the whole thing if
|
1120
|
+
# $DEBUG (ruby) or $MT_DEBUG (env).
|
946
1121
|
|
947
1122
|
def filter bt
|
948
1123
|
return ["No backtrace"] unless bt
|
949
1124
|
|
950
|
-
return bt.dup if $DEBUG
|
1125
|
+
return bt.dup if $DEBUG || ENV["MT_DEBUG"]
|
951
1126
|
|
952
|
-
new_bt = bt.take_while { |line| line !~
|
953
|
-
new_bt = bt.select { |line| line !~
|
954
|
-
new_bt = bt.dup
|
1127
|
+
new_bt = bt.take_while { |line| line.to_s !~ regexp }
|
1128
|
+
new_bt = bt.select { |line| line.to_s !~ regexp } if new_bt.empty?
|
1129
|
+
new_bt = bt.dup if new_bt.empty?
|
955
1130
|
|
956
1131
|
new_bt
|
957
1132
|
end
|
@@ -6,8 +6,28 @@ class Minitest::Test
|
|
6
6
|
def clean s
|
7
7
|
s.gsub(/^ {6}/, "")
|
8
8
|
end
|
9
|
+
|
10
|
+
def with_empty_backtrace_filter
|
11
|
+
with_backtrace_filter Minitest::BacktraceFilter.new %r%.% do
|
12
|
+
yield
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_backtrace_filter filter
|
17
|
+
original = Minitest.backtrace_filter
|
18
|
+
|
19
|
+
Minitest::Test.io_lock.synchronize do # try not to trounce in parallel
|
20
|
+
begin
|
21
|
+
Minitest.backtrace_filter = filter
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
Minitest.backtrace_filter = original
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
9
28
|
end
|
10
29
|
|
30
|
+
|
11
31
|
class FakeNamedTest < Minitest::Test
|
12
32
|
@@count = 0
|
13
33
|
|
@@ -25,6 +45,14 @@ class AnError < StandardError; include MyModule; end
|
|
25
45
|
class MetaMetaMetaTestCase < Minitest::Test
|
26
46
|
attr_accessor :reporter, :output, :tu
|
27
47
|
|
48
|
+
def with_stderr err
|
49
|
+
old = $stderr
|
50
|
+
$stderr = err
|
51
|
+
yield
|
52
|
+
ensure
|
53
|
+
$stderr = old
|
54
|
+
end
|
55
|
+
|
28
56
|
def run_tu_with_fresh_reporter flags = %w[--seed 42]
|
29
57
|
options = Minitest.process_args flags
|
30
58
|
|
@@ -34,18 +62,20 @@ class MetaMetaMetaTestCase < Minitest::Test
|
|
34
62
|
reporter << Minitest::SummaryReporter.new(@output, options)
|
35
63
|
reporter << Minitest::ProgressReporter.new(@output, options)
|
36
64
|
|
37
|
-
|
65
|
+
with_stderr @output do
|
66
|
+
reporter.start
|
38
67
|
|
39
|
-
|
68
|
+
yield(reporter) if block_given?
|
40
69
|
|
41
|
-
|
42
|
-
|
43
|
-
|
70
|
+
@tus ||= [@tu]
|
71
|
+
@tus.each do |tu|
|
72
|
+
Minitest::Runnable.runnables.delete tu
|
44
73
|
|
45
|
-
|
46
|
-
|
74
|
+
tu.run reporter, options
|
75
|
+
end
|
47
76
|
|
48
|
-
|
77
|
+
reporter.report
|
78
|
+
end
|
49
79
|
end
|
50
80
|
|
51
81
|
def first_reporter
|
@@ -76,14 +106,18 @@ class MetaMetaMetaTestCase < Minitest::Test
|
|
76
106
|
output.gsub!(/0x[A-Fa-f0-9]+/, "0xXXX")
|
77
107
|
output.gsub!(/ +$/, "")
|
78
108
|
|
109
|
+
file = ->(s) { s.start_with?("/") ? "FULLFILE" : "FILE" }
|
110
|
+
|
79
111
|
if windows? then
|
80
112
|
output.gsub!(/\[(?:[A-Za-z]:)?[^\]:]+:\d+\]/, "[FILE:LINE]")
|
81
113
|
output.gsub!(/^(\s+)(?:[A-Za-z]:)?[^:]+:\d+:in/, '\1FILE:LINE:in')
|
82
114
|
else
|
83
|
-
output.gsub!(/\[[^\]:]
|
84
|
-
output.gsub!(/^(\s+)[^:]
|
115
|
+
output.gsub!(/\[([^\]:]+):\d+\]/) { "[#{file[$1]}:LINE]" }
|
116
|
+
output.gsub!(/^(\s+)([^:]+):\d+:in/) { "#{$1}#{file[$2]}:LINE:in" }
|
85
117
|
end
|
86
118
|
|
119
|
+
output.gsub!(/( at )[^:]+:\d+/) { "#{$1}[#{file[$2]}:LINE]" } # eval?
|
120
|
+
|
87
121
|
output
|
88
122
|
end
|
89
123
|
|
@@ -98,7 +132,7 @@ class MetaMetaMetaTestCase < Minitest::Test
|
|
98
132
|
|
99
133
|
def setup
|
100
134
|
super
|
101
|
-
|
135
|
+
Minitest.seed = 42
|
102
136
|
Minitest::Test.reset
|
103
137
|
@tu = nil
|
104
138
|
end
|