minitest 5.23.1 → 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.
data/lib/minitest.rb CHANGED
@@ -9,7 +9,7 @@ require_relative "minitest/compress"
9
9
  # :include: README.rdoc
10
10
 
11
11
  module Minitest
12
- VERSION = "5.23.1" # :nodoc:
12
+ VERSION = "5.25.1" # :nodoc:
13
13
 
14
14
  @@installed_at_exit ||= false
15
15
  @@after_run = []
@@ -67,9 +67,8 @@ module Minitest
67
67
  # Registers Minitest to run at process exit
68
68
 
69
69
  def self.autorun
70
- if Object.const_defined?(:Warning) && Warning.respond_to?(:[]=)
71
- Warning[:deprecated] = true
72
- end
70
+ Warning[:deprecated] = true if
71
+ Object.const_defined?(:Warning) && Warning.respond_to?(:[]=)
73
72
 
74
73
  at_exit {
75
74
  next if $! and not ($!.kind_of? SystemExit and $!.success?)
@@ -98,20 +97,19 @@ module Minitest
98
97
  @@after_run << block
99
98
  end
100
99
 
101
- def self.init_plugins options # :nodoc:
102
- self.extensions.each do |name|
103
- msg = "plugin_#{name}_init"
104
- send msg, options if self.respond_to? msg
105
- end
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
106
106
  end
107
107
 
108
108
  def self.load_plugins # :nodoc:
109
- return unless self.extensions.empty?
109
+ return unless defined? Gem
110
110
 
111
111
  seen = {}
112
112
 
113
- require "rubygems" unless defined? Gem
114
-
115
113
  Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
116
114
  name = File.basename plugin_path, "_plugin.rb"
117
115
 
@@ -123,93 +121,27 @@ module Minitest
123
121
  end
124
122
  end
125
123
 
126
- ##
127
- # This is the top-level run method. Everything starts from here. It
128
- # tells each Runnable sub-class to run, and each of those are
129
- # responsible for doing whatever they do.
130
- #
131
- # The overall structure of a run looks like this:
132
- #
133
- # Minitest.autorun
134
- # Minitest.run(args)
135
- # Minitest.__run(reporter, options)
136
- # Runnable.runnables.each
137
- # runnable_klass.run(reporter, options)
138
- # self.runnable_methods.each
139
- # self.run_one_method(self, runnable_method, reporter)
140
- # Minitest.run_one_method(klass, runnable_method)
141
- # klass.new(runnable_method).run
142
-
143
- def self.run args = []
144
- self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
145
-
146
- options = process_args args
147
-
148
- Minitest.seed = options[:seed]
149
- srand Minitest.seed
150
-
151
- reporter = CompositeReporter.new
152
- reporter << SummaryReporter.new(options[:io], options)
153
- reporter << ProgressReporter.new(options[:io], options) unless options[:quiet]
154
-
155
- self.reporter = reporter # this makes it available to plugins
156
- self.init_plugins options
157
- self.reporter = nil # runnables shouldn't depend on the reporter, ever
158
-
159
- self.parallel_executor.start if parallel_executor.respond_to?(:start)
160
- reporter.start
161
- begin
162
- __run reporter, options
163
- rescue Interrupt
164
- 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
165
139
  end
166
- self.parallel_executor.shutdown
167
-
168
- # might have been removed/replaced during init_plugins:
169
- summary = reporter.reporters.grep(SummaryReporter).first
170
-
171
- reporter.report
172
-
173
- return empty_run! options if summary && summary.count == 0
174
- reporter.passed?
175
- end
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
-
193
- ##
194
- # Internal run method. Responsible for telling all Runnable
195
- # sub-classes to run.
196
-
197
- def self.__run reporter, options
198
- suites = Runnable.runnables.shuffle
199
- parallel, serial = suites.partition { |s| s.test_order == :parallel }
200
-
201
- # If we run the parallel tests before the serial tests, the parallel tests
202
- # could run in parallel with the serial tests. This would be bad because
203
- # the serial tests won't lock around Reporter#record. Run the serial tests
204
- # first, so that after they complete, the parallel tests will lock when
205
- # recording results.
206
- serial.map { |suite| suite.run reporter, options } +
207
- parallel.map { |suite| suite.run reporter, options }
208
140
  end
209
141
 
210
142
  def self.process_args args = [] # :nodoc:
211
143
  options = {
212
- :io => $stdout,
144
+ :io => $stdout,
213
145
  }
214
146
  orig_args = args.dup
215
147
 
@@ -253,7 +185,7 @@ module Minitest
253
185
  options[:skip] = s.chars.to_a
254
186
  end
255
187
 
256
- ruby27plus = ::Warning.respond_to?(:[]=)
188
+ ruby27plus = ::Warning.respond_to? :[]=
257
189
 
258
190
  opts.on "-W[error]", String, "Turn Ruby warnings into errors" do |s|
259
191
  options[:Werror] = true
@@ -269,11 +201,21 @@ module Minitest
269
201
 
270
202
  unless extensions.empty?
271
203
  opts.separator ""
272
- opts.separator "Known extensions: #{extensions.join(", ")}"
273
-
274
- extensions.each do |meth|
275
- msg = "plugin_#{meth}_options"
276
- send msg, opts, options if self.respond_to?(msg)
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
277
219
  end
278
220
  end
279
221
 
@@ -297,12 +239,99 @@ module Minitest
297
239
  end
298
240
 
299
241
  options[:args] = orig_args.map { |s|
300
- s =~ /[\s|&<>$()]/ ? s.inspect : s
242
+ s.match?(/[\s|&<>$()]/) ? s.inspect : s
301
243
  }.join " "
302
244
 
303
245
  options
304
246
  end
305
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
+
306
335
  def self.filter_backtrace bt # :nodoc:
307
336
  result = backtrace_filter.filter bt
308
337
  result = bt.dup if result.empty?
@@ -376,8 +405,8 @@ module Minitest
376
405
  pos = options[:filter]
377
406
  neg = options[:exclude]
378
407
 
379
- pos = Regexp.new $1 if pos.is_a?(String) && pos =~ %r%/(.*)/%
380
- neg = Regexp.new $1 if neg.is_a?(String) && neg =~ %r%/(.*)/%
408
+ pos = Regexp.new $1 if pos.kind_of?(String) && pos =~ %r%/(.*)/%
409
+ neg = Regexp.new $1 if neg.kind_of?(String) && neg =~ %r%/(.*)/%
381
410
 
382
411
  filtered_methods = self.runnable_methods
383
412
  .select { |m| !pos || pos === m || pos === "#{self}##{m}" }
@@ -385,8 +414,22 @@ module Minitest
385
414
 
386
415
  return if filtered_methods.empty?
387
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
+
388
428
  with_info_handler reporter do
389
429
  filtered_methods.each do |method_name|
430
+ name = method_name
431
+ t0 = Minitest.clock_time
432
+
390
433
  run_one_method self, method_name, reporter
391
434
  end
392
435
  end
@@ -412,16 +455,7 @@ module Minitest
412
455
  end
413
456
 
414
457
  def self.with_info_handler reporter, &block # :nodoc:
415
- handler = lambda do
416
- unless reporter.passed? then
417
- warn "Current results:"
418
- warn ""
419
- warn reporter.reporters.first
420
- warn ""
421
- end
422
- end
423
-
424
- on_signal ::Minitest.info_signal, handler, &block
458
+ on_signal ::Minitest.info_signal, @_info_handler, &block
425
459
  end
426
460
 
427
461
  SIGNALS = Signal.list # :nodoc:
@@ -459,7 +493,7 @@ module Minitest
459
493
  def marshal_dump # :nodoc:
460
494
  unless @@marshal_dump_warned then
461
495
  warn ["Minitest::Runnable#marshal_dump is deprecated.",
462
- "You might be violating internals. From", caller.first].join " "
496
+ "You might be violating internals. From", caller(1..1).first].join " "
463
497
  @@marshal_dump_warned = true
464
498
  end
465
499
 
@@ -587,7 +621,7 @@ module Minitest
587
621
  # Did this run error?
588
622
 
589
623
  def error?
590
- self.failures.any? { |f| UnexpectedError === f }
624
+ self.failures.any? UnexpectedError
591
625
  end
592
626
  end
593
627
 
@@ -690,7 +724,7 @@ module Minitest
690
724
  true
691
725
  end
692
726
 
693
- def synchronize(&block) # :nodoc:
727
+ def synchronize &block # :nodoc:
694
728
  @mutex.synchronize(&block)
695
729
  end
696
730
  end
@@ -722,11 +756,11 @@ module Minitest
722
756
  # own.
723
757
 
724
758
  class ProgressReporter < Reporter
725
- def prerecord klass, name #:nodoc:
726
- if options[:verbose] then
727
- io.print "%s#%s = " % [klass.name, name]
728
- io.flush
729
- end
759
+ def prerecord klass, name # :nodoc:
760
+ return unless options[:verbose]
761
+
762
+ io.print "%s#%s = " % [klass.name, name]
763
+ io.flush
730
764
  end
731
765
 
732
766
  def record result # :nodoc:
@@ -860,10 +894,8 @@ module Minitest
860
894
  # own.
861
895
 
862
896
  class SummaryReporter < StatisticsReporter
863
- # :stopdoc:
864
- attr_accessor :sync
865
- attr_accessor :old_sync
866
- # :startdoc:
897
+ attr_accessor :sync # :nodoc:
898
+ attr_accessor :old_sync # :nodoc:
867
899
 
868
900
  def start # :nodoc:
869
901
  super
@@ -911,20 +943,22 @@ module Minitest
911
943
  end
912
944
 
913
945
  def to_s # :nodoc:
914
- aggregated_results(StringIO.new(''.b)).string
946
+ aggregated_results(StringIO.new("".b)).string
915
947
  end
916
948
 
917
949
  def summary # :nodoc:
918
- extra = ""
950
+ extra = []
919
951
 
920
- extra = "\n\nYou have skipped tests. Run with --verbose for details." if
921
- results.any?(&:skipped?) unless
922
- options[:verbose] or options[:show_skips] or ENV["MT_NO_SKIP_MSG"]
952
+ extra << ", %d warnings" % [warnings] if options[:Werror]
923
953
 
924
- extra.prepend ", %d warnings" % [warnings] if options[:Werror]
954
+ extra << "\n\nYou have skipped tests. Run with --verbose for details." if
955
+ results.any?(&:skipped?) unless
956
+ options[:verbose] or
957
+ options[:show_skips] or
958
+ ENV["MT_NO_SKIP_MSG"]
925
959
 
926
960
  "%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
927
- [count, assertions, failures, errors, skips, extra]
961
+ [count, assertions, failures, errors, skips, extra.join]
928
962
  end
929
963
  end
930
964
 
@@ -1095,7 +1129,7 @@ module Minitest
1095
1129
 
1096
1130
  def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
1097
1131
  where = Minitest.filter_backtrace(caller).first
1098
- where = where.split(/:in /, 2).first # clean up noise
1132
+ where = where.split(":in ", 2).first # clean up noise
1099
1133
  warn "DEPRECATED: `maglev?` called from #{where}. This will fail in Minitest 6."
1100
1134
  "maglev" == platform
1101
1135
  end
@@ -1104,14 +1138,14 @@ module Minitest
1104
1138
  # Is this running on mri?
1105
1139
 
1106
1140
  def mri? platform = RUBY_DESCRIPTION
1107
- /^ruby/ =~ platform
1141
+ platform.start_with? "ruby"
1108
1142
  end
1109
1143
 
1110
1144
  ##
1111
1145
  # Is this running on macOS?
1112
1146
 
1113
1147
  def osx? platform = RUBY_PLATFORM
1114
- /darwin/ =~ platform
1148
+ platform.include? "darwin"
1115
1149
  end
1116
1150
 
1117
1151
  ##
@@ -1119,7 +1153,7 @@ module Minitest
1119
1153
 
1120
1154
  def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
1121
1155
  where = Minitest.filter_backtrace(caller).first
1122
- where = where.split(/:in /, 2).first # clean up noise
1156
+ where = where.split(":in ", 2).first # clean up noise
1123
1157
  warn "DEPRECATED: `rubinius?` called from #{where}. This will fail in Minitest 6."
1124
1158
  "rbx" == platform
1125
1159
  end
@@ -1128,7 +1162,7 @@ module Minitest
1128
1162
  # Is this running on windows?
1129
1163
 
1130
1164
  def windows? platform = RUBY_PLATFORM
1131
- /mswin|mingw/ =~ platform
1165
+ /mswin|mingw/.match? platform
1132
1166
  end
1133
1167
  end
1134
1168
 
@@ -1139,11 +1173,14 @@ module Minitest
1139
1173
 
1140
1174
  class BacktraceFilter
1141
1175
 
1142
- MT_RE = %r%lib/minitest|internal:warning% #:nodoc:
1176
+ MT_RE = %r%lib/minitest|internal:warning% # :nodoc:
1177
+
1178
+ ##
1179
+ # The regular expression to use to filter backtraces. Defaults to +MT_RE+.
1143
1180
 
1144
1181
  attr_accessor :regexp
1145
1182
 
1146
- def initialize regexp = MT_RE
1183
+ def initialize regexp = MT_RE # :nodoc:
1147
1184
  self.regexp = regexp
1148
1185
  end
1149
1186
 
@@ -1156,9 +1193,9 @@ module Minitest
1156
1193
 
1157
1194
  return bt.dup if $DEBUG || ENV["MT_DEBUG"]
1158
1195
 
1159
- new_bt = bt.take_while { |line| line.to_s !~ regexp }
1160
- new_bt = bt.select { |line| line.to_s !~ regexp } if new_bt.empty?
1161
- new_bt = bt.dup if new_bt.empty?
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?
1162
1199
 
1163
1200
  new_bt
1164
1201
  end
@@ -3,10 +3,6 @@ require "stringio"
3
3
  require "minitest/autorun"
4
4
 
5
5
  class Minitest::Test
6
- def clean s
7
- s.gsub(/^ {6}/, "")
8
- end
9
-
10
6
  def with_empty_backtrace_filter
11
7
  with_backtrace_filter Minitest::BacktraceFilter.new %r%.% do
12
8
  yield
@@ -31,6 +27,7 @@ class Minitest::Test
31
27
  end
32
28
 
33
29
  def assert_deprecation re = /DEPRECATED/
30
+ re = // if $-w.nil? # "skip" if running `rake testW0`
34
31
  assert_output "", re do
35
32
  yield
36
33
  end
@@ -67,7 +64,7 @@ class MetaMetaMetaTestCase < Minitest::Test
67
64
  def run_tu_with_fresh_reporter flags = %w[--seed 42]
68
65
  options = Minitest.process_args flags
69
66
 
70
- @output = StringIO.new("".encode(Encoding::UTF_8))
67
+ @output = StringIO.new(+"")
71
68
 
72
69
  self.reporter = Minitest::CompositeReporter.new
73
70
  reporter << Minitest::SummaryReporter.new(@output, options)
@@ -76,7 +73,7 @@ class MetaMetaMetaTestCase < Minitest::Test
76
73
  with_stderr @output do
77
74
  reporter.start
78
75
 
79
- yield(reporter) if block_given?
76
+ yield reporter if block_given?
80
77
 
81
78
  @tus ||= [@tu]
82
79
  @tus.each do |tu|
@@ -94,8 +91,8 @@ class MetaMetaMetaTestCase < Minitest::Test
94
91
  end
95
92
 
96
93
  def assert_report expected, flags = %w[--seed 42], &block
97
- header = clean <<-EOM
98
- Run options: #{flags.map { |s| s =~ /\|/ ? s.inspect : s }.join " "}
94
+ header = <<~EOM
95
+ Run options: #{flags.map { |s| s.include?("|") ? s.inspect : s }.join " "}
99
96
 
100
97
  # Running:
101
98
 
@@ -130,7 +127,7 @@ class MetaMetaMetaTestCase < Minitest::Test
130
127
  output.gsub!(/in [`']block in (?:([^']+)[#.])?/, "in 'block in")
131
128
  output.gsub!(/in [`'](?:([^']+)[#.])?/, "in '")
132
129
 
133
- output.gsub!(/( at )[^:]+:\d+/) { "#{$1}[#{file[$2]}:LINE]" } # eval?
130
+ output.gsub!(/( at )([^:]+):\d+/) { "#{$1}[#{file[$2]}:LINE]" } # eval?
134
131
 
135
132
  output
136
133
  end