minitest 5.23.1 → 5.25.1

Sign up to get free protection for your applications and to get access to all the features.
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