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.
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