minitest 5.12.0 → 5.22.2

Sign up to get free protection for your applications and to get access to all the features.
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.0" # :nodoc:
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
- mc = (class << self; self; end)
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
- mc.send :attr_accessor, :parallel_executor
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
- mc.send :attr_accessor, :backtrace_filter
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
- mc.send :attr_accessor, :reporter
50
+ cattr_accessor :reporter
40
51
 
41
52
  ##
42
53
  # Names of known extension plugins.
43
54
 
44
- mc.send :attr_accessor, :extensions
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
- mc.send :attr_accessor, :info_signal
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
- # runnable.run(reporter, options)
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.reject { |s| s.runnable_methods.empty? }.shuffle
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
- filter = options[:filter] || "/./"
307
- filter = Regexp.new $1 if filter.is_a?(String) && filter =~ %r%/(.*)/%
362
+ pos = options[:filter]
363
+ neg = options[:exclude]
308
364
 
309
- filtered_methods = self.runnable_methods.find_all { |m|
310
- filter === m || filter === "#{self}##{m}"
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.delete_if { |m|
317
- exclude === m || exclude === "#{self}##{m}"
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. Eg ".", "F", or "E".
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
- include Mutex_m
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
- # Record a result and output the Runnable#result_code. Stores the
567
- # result of the run if the run did not pass.
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
- # :stopdoc:
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
- def report # :nodoc:
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=" # stupid emacs
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 options[:verbose]
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(binary_string)).string
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 options[:verbose] or ENV["MT_NO_SKIP_MSG"]
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
- last_before_assertion = ""
828
- self.backtrace.reverse_each do |s|
829
- break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
830
- last_before_assertion = s
831
- end
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
- attr_accessor :exception # :nodoc:
1002
+ include Minitest::Compress
858
1003
 
859
- def initialize exception # :nodoc:
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
- self.exception = exception
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.exception.backtrace
1021
+ self.error.backtrace
866
1022
  end
867
1023
 
868
- def error # :nodoc:
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 "\n "
874
- "#{self.exception.class}: #{self.exception.message}\n #{bt}"
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 $DEBUG.
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 !~ MT_RE }
953
- new_bt = bt.select { |line| line !~ MT_RE } if new_bt.empty?
954
- new_bt = bt.dup if new_bt.empty?
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
- reporter.start
65
+ with_stderr @output do
66
+ reporter.start
38
67
 
39
- yield(reporter) if block_given?
68
+ yield(reporter) if block_given?
40
69
 
41
- @tus ||= [@tu]
42
- @tus.each do |tu|
43
- Minitest::Runnable.runnables.delete tu
70
+ @tus ||= [@tu]
71
+ @tus.each do |tu|
72
+ Minitest::Runnable.runnables.delete tu
44
73
 
45
- tu.run reporter, options
46
- end
74
+ tu.run reporter, options
75
+ end
47
76
 
48
- reporter.report
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!(/\[[^\]:]+:\d+\]/, "[FILE:LINE]")
84
- output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in')
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
- srand 42
135
+ Minitest.seed = 42
102
136
  Minitest::Test.reset
103
137
  @tu = nil
104
138
  end