minitest 5.16.2 → 6.0.5
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 +373 -1
- data/Manifest.txt +16 -4
- data/README.rdoc +48 -118
- data/Rakefile +17 -2
- data/bin/minitest +5 -0
- data/design_rationale.rb +21 -19
- data/lib/hoe/minitest.rb +4 -2
- data/lib/minitest/assertions.rb +142 -124
- data/lib/minitest/autorun.rb +3 -11
- data/lib/minitest/benchmark.rb +9 -12
- data/lib/minitest/bisect.rb +304 -0
- data/lib/minitest/complete.rb +56 -0
- data/lib/minitest/compress.rb +94 -0
- data/lib/minitest/error_on_warning.rb +11 -0
- data/lib/minitest/expectations.rb +18 -0
- data/lib/minitest/find_minimal_combination.rb +127 -0
- data/lib/minitest/hell.rb +1 -1
- data/lib/minitest/manual_plugins.rb +4 -0
- data/lib/minitest/parallel.rb +10 -8
- data/lib/minitest/path_expander.rb +432 -0
- data/lib/minitest/pride.rb +2 -2
- data/lib/minitest/pride_plugin.rb +17 -24
- data/lib/minitest/server.rb +49 -0
- data/lib/minitest/server_plugin.rb +88 -0
- data/lib/minitest/spec.rb +27 -46
- data/lib/minitest/sprint.rb +105 -0
- data/lib/minitest/sprint_plugin.rb +39 -0
- data/lib/minitest/test.rb +32 -52
- data/lib/minitest/test_task.rb +68 -42
- data/lib/minitest.rb +361 -215
- data/test/minitest/metametameta.rb +33 -19
- data/test/minitest/test_bisect.rb +249 -0
- data/test/minitest/test_find_minimal_combination.rb +138 -0
- data/test/minitest/test_minitest_assertions.rb +311 -173
- data/test/minitest/test_minitest_benchmark.rb +15 -1
- data/test/minitest/test_minitest_reporter.rb +148 -23
- data/test/minitest/test_minitest_spec.rb +157 -132
- data/test/minitest/test_minitest_test.rb +270 -204
- data/test/minitest/test_minitest_test_task.rb +18 -7
- data/test/minitest/test_path_expander.rb +229 -0
- data/test/minitest/test_server.rb +146 -0
- data.tar.gz.sig +2 -2
- metadata +97 -37
- metadata.gz.sig +0 -0
- data/.autotest +0 -34
- data/lib/minitest/mock.rb +0 -323
- data/lib/minitest/unit.rb +0 -42
- data/test/minitest/test_minitest_mock.rb +0 -1139
data/lib/minitest.rb
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
require "optparse"
|
|
2
|
-
require "thread"
|
|
3
|
-
require "mutex_m"
|
|
4
|
-
require "minitest/parallel"
|
|
5
2
|
require "stringio"
|
|
6
3
|
require "etc"
|
|
7
4
|
|
|
5
|
+
require_relative "minitest/parallel"
|
|
6
|
+
require_relative "minitest/compress"
|
|
7
|
+
|
|
8
8
|
##
|
|
9
|
-
#
|
|
9
|
+
# The top-level namespace for Minitest. Also the location of the main
|
|
10
|
+
# runtime. See +Minitest.run+ for more information.
|
|
10
11
|
|
|
11
12
|
module Minitest
|
|
12
|
-
VERSION = "
|
|
13
|
+
VERSION = "6.0.4" # :nodoc:
|
|
13
14
|
|
|
14
15
|
@@installed_at_exit ||= false
|
|
15
16
|
@@after_run = []
|
|
@@ -32,10 +33,9 @@ module Minitest
|
|
|
32
33
|
|
|
33
34
|
cattr_accessor :parallel_executor
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
n_threads = (ENV["MT_CPU"] || ENV["N"] || Etc.nprocessors).to_i
|
|
36
|
+
n_threads = (ENV["MT_CPU"] || Etc.nprocessors).to_i
|
|
37
37
|
|
|
38
|
-
self.parallel_executor = Parallel::Executor.new n_threads
|
|
38
|
+
self.parallel_executor = Parallel::Executor.new n_threads if n_threads > 1
|
|
39
39
|
|
|
40
40
|
##
|
|
41
41
|
# Filter object for backtraces.
|
|
@@ -60,13 +60,14 @@ module Minitest
|
|
|
60
60
|
cattr_accessor :info_signal
|
|
61
61
|
self.info_signal = "INFO"
|
|
62
62
|
|
|
63
|
+
cattr_accessor :allow_fork
|
|
64
|
+
self.allow_fork = false
|
|
65
|
+
|
|
63
66
|
##
|
|
64
67
|
# Registers Minitest to run at process exit
|
|
65
68
|
|
|
66
69
|
def self.autorun
|
|
67
|
-
|
|
68
|
-
Warning[:deprecated] = true
|
|
69
|
-
end
|
|
70
|
+
Warning[:deprecated] = true
|
|
70
71
|
|
|
71
72
|
at_exit {
|
|
72
73
|
next if $! and not ($!.kind_of? SystemExit and $!.success?)
|
|
@@ -75,7 +76,7 @@ module Minitest
|
|
|
75
76
|
|
|
76
77
|
pid = Process.pid
|
|
77
78
|
at_exit {
|
|
78
|
-
next if Process.pid != pid
|
|
79
|
+
next if !Minitest.allow_fork && Process.pid != pid
|
|
79
80
|
@@after_run.reverse_each(&:call)
|
|
80
81
|
exit exit_code || false
|
|
81
82
|
}
|
|
@@ -95,20 +96,30 @@ module Minitest
|
|
|
95
96
|
@@after_run << block
|
|
96
97
|
end
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
##
|
|
100
|
+
# Manually load plugins by name.
|
|
101
|
+
|
|
102
|
+
def self.load *names
|
|
103
|
+
names.each do |name|
|
|
104
|
+
require "minitest/#{name}_plugin"
|
|
105
|
+
|
|
106
|
+
self.extensions << name.to_s
|
|
102
107
|
end
|
|
103
108
|
end
|
|
104
109
|
|
|
110
|
+
##
|
|
111
|
+
# Register a plugin to be used. Does NOT require / load it.
|
|
112
|
+
|
|
113
|
+
def self.register_plugin name_or_mod
|
|
114
|
+
self.extensions << name_or_mod
|
|
115
|
+
nil
|
|
116
|
+
end
|
|
117
|
+
|
|
105
118
|
def self.load_plugins # :nodoc:
|
|
106
|
-
return unless
|
|
119
|
+
return unless defined? Gem
|
|
107
120
|
|
|
108
121
|
seen = {}
|
|
109
122
|
|
|
110
|
-
require "rubygems" unless defined? Gem
|
|
111
|
-
|
|
112
123
|
Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
|
|
113
124
|
name = File.basename plugin_path, "_plugin.rb"
|
|
114
125
|
|
|
@@ -120,118 +131,122 @@ module Minitest
|
|
|
120
131
|
end
|
|
121
132
|
end
|
|
122
133
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# klass.new(runnable_method).run
|
|
139
|
-
|
|
140
|
-
def self.run args = []
|
|
141
|
-
self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
|
|
142
|
-
|
|
143
|
-
options = process_args args
|
|
144
|
-
|
|
145
|
-
Minitest.seed = options[:seed]
|
|
146
|
-
srand Minitest.seed
|
|
147
|
-
|
|
148
|
-
reporter = CompositeReporter.new
|
|
149
|
-
reporter << SummaryReporter.new(options[:io], options)
|
|
150
|
-
reporter << ProgressReporter.new(options[:io], options)
|
|
151
|
-
|
|
152
|
-
self.reporter = reporter # this makes it available to plugins
|
|
153
|
-
self.init_plugins options
|
|
154
|
-
self.reporter = nil # runnables shouldn't depend on the reporter, ever
|
|
155
|
-
|
|
156
|
-
self.parallel_executor.start if parallel_executor.respond_to?(:start)
|
|
157
|
-
reporter.start
|
|
158
|
-
begin
|
|
159
|
-
__run reporter, options
|
|
160
|
-
rescue Interrupt
|
|
161
|
-
warn "Interrupted. Exiting..."
|
|
134
|
+
def self.init_plugins options # :nodoc:
|
|
135
|
+
self.extensions.each do |mod_or_meth|
|
|
136
|
+
case mod_or_meth
|
|
137
|
+
when Symbol, String then
|
|
138
|
+
name = mod_or_meth
|
|
139
|
+
msg = "plugin_#{name}_init"
|
|
140
|
+
next unless self.respond_to? msg
|
|
141
|
+
send msg, options
|
|
142
|
+
when Module then
|
|
143
|
+
recv = mod_or_meth
|
|
144
|
+
next unless recv.respond_to? :minitest_plugin_init
|
|
145
|
+
recv.minitest_plugin_init options
|
|
146
|
+
else
|
|
147
|
+
raise ArgumentError, "plugin is %p, but it must be a symbol, string or module" % [mod_or_meth]
|
|
148
|
+
end
|
|
162
149
|
end
|
|
163
|
-
self.parallel_executor.shutdown
|
|
164
|
-
reporter.report
|
|
165
|
-
|
|
166
|
-
reporter.passed?
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
##
|
|
170
|
-
# Internal run method. Responsible for telling all Runnable
|
|
171
|
-
# sub-classes to run.
|
|
172
|
-
|
|
173
|
-
def self.__run reporter, options
|
|
174
|
-
suites = Runnable.runnables.shuffle
|
|
175
|
-
parallel, serial = suites.partition { |s| s.test_order == :parallel }
|
|
176
|
-
|
|
177
|
-
# If we run the parallel tests before the serial tests, the parallel tests
|
|
178
|
-
# could run in parallel with the serial tests. This would be bad because
|
|
179
|
-
# the serial tests won't lock around Reporter#record. Run the serial tests
|
|
180
|
-
# first, so that after they complete, the parallel tests will lock when
|
|
181
|
-
# recording results.
|
|
182
|
-
serial.map { |suite| suite.run reporter, options } +
|
|
183
|
-
parallel.map { |suite| suite.run reporter, options }
|
|
184
150
|
end
|
|
185
151
|
|
|
186
152
|
def self.process_args args = [] # :nodoc:
|
|
187
153
|
options = {
|
|
188
|
-
|
|
154
|
+
:io => $stdout,
|
|
189
155
|
}
|
|
190
156
|
orig_args = args.dup
|
|
191
157
|
|
|
158
|
+
warn "--no-plugins is a no-op" if args.delete "--no-plugins" # TODO: remove me! when?
|
|
159
|
+
|
|
192
160
|
OptionParser.new do |opts|
|
|
193
|
-
opts.
|
|
161
|
+
opts.program_name = "minitest"
|
|
194
162
|
opts.version = Minitest::VERSION
|
|
195
163
|
|
|
164
|
+
opts.banner = [
|
|
165
|
+
"Usage: minitest [paths] [options]",
|
|
166
|
+
"ruby path/to/test.rb [options]",
|
|
167
|
+
"rake test [A=options] (see Minitest::TestTask for more options)\n\n",
|
|
168
|
+
].join "\n or: "
|
|
169
|
+
|
|
196
170
|
opts.on "-h", "--help", "Display this help." do
|
|
197
171
|
puts opts
|
|
198
|
-
exit
|
|
172
|
+
exit! true
|
|
199
173
|
end
|
|
200
174
|
|
|
201
|
-
opts.on "
|
|
175
|
+
opts.on "-V", "--version", "Display the version." do
|
|
176
|
+
puts "#{opts.program_name} #{Minitest::VERSION}"
|
|
177
|
+
exit! true
|
|
178
|
+
end
|
|
202
179
|
|
|
203
|
-
desc = "Sets random seed. Also via env
|
|
180
|
+
desc = "Sets random seed. Also via env, eg: SEED=42"
|
|
204
181
|
opts.on "-s", "--seed SEED", Integer, desc do |m|
|
|
205
|
-
options[:seed] = m
|
|
182
|
+
options[:seed] = m
|
|
206
183
|
end
|
|
207
184
|
|
|
208
|
-
opts.on "-v", "--verbose", "Verbose.
|
|
185
|
+
opts.on "-v", "--verbose", "Verbose. Print each name as they run." do
|
|
209
186
|
options[:verbose] = true
|
|
210
187
|
end
|
|
211
188
|
|
|
189
|
+
opts.on "-q", "--quiet", "Quiet. Show no dots while processing files." do
|
|
190
|
+
options[:quiet] = true
|
|
191
|
+
end
|
|
192
|
+
|
|
212
193
|
opts.on "--show-skips", "Show skipped at the end of run." do
|
|
213
194
|
options[:show_skips] = true
|
|
214
195
|
end
|
|
215
196
|
|
|
216
|
-
opts.on "-
|
|
217
|
-
|
|
197
|
+
opts.on "-b", "--bisect", "Run minitest in bisect-mode to isolate flaky tests." if
|
|
198
|
+
File.basename($0).match?(/minitest/)
|
|
199
|
+
|
|
200
|
+
opts.on "-i", "--include PATTERN", "Include /regexp/ or string for run." do |a|
|
|
201
|
+
options[:include] = a
|
|
218
202
|
end
|
|
219
203
|
|
|
220
204
|
opts.on "-e", "--exclude PATTERN", "Exclude /regexp/ or string from run." do |a|
|
|
221
205
|
options[:exclude] = a
|
|
222
206
|
end
|
|
223
207
|
|
|
208
|
+
# part of my unofficial embedded gem "makeoptparseworkwell"
|
|
209
|
+
def opts.topdict(name) = (name.length > 1 ? top.long : top.short)
|
|
210
|
+
def opts.alias(from, to) = (dict = topdict(from) ; dict[to] = dict[from])
|
|
211
|
+
|
|
212
|
+
# these will work but won't show up in --help output:
|
|
213
|
+
opts.alias "include", "name"
|
|
214
|
+
opts.alias "i", "n"
|
|
215
|
+
opts.alias "e", "x"
|
|
216
|
+
|
|
224
217
|
opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s|
|
|
225
218
|
options[:skip] = s.chars.to_a
|
|
226
219
|
end
|
|
227
220
|
|
|
221
|
+
opts.on "-W[error]", String, "Turn Ruby warnings into errors" do |s|
|
|
222
|
+
options[:Werror] = true
|
|
223
|
+
case s
|
|
224
|
+
when "error", "all", nil then
|
|
225
|
+
require_relative "minitest/error_on_warning"
|
|
226
|
+
$VERBOSE = true
|
|
227
|
+
::Warning[:deprecated] = true
|
|
228
|
+
else
|
|
229
|
+
::Warning[s.to_sym] = true # check validity of category
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
228
233
|
unless extensions.empty?
|
|
229
234
|
opts.separator ""
|
|
230
|
-
opts.separator "Known extensions: #{extensions.join
|
|
231
|
-
|
|
232
|
-
extensions.each do |
|
|
233
|
-
|
|
234
|
-
|
|
235
|
+
opts.separator "Known extensions: #{extensions.join ", "}"
|
|
236
|
+
|
|
237
|
+
extensions.each do |mod_or_meth|
|
|
238
|
+
case mod_or_meth
|
|
239
|
+
when Symbol, String then
|
|
240
|
+
meth = mod_or_meth
|
|
241
|
+
msg = "plugin_#{meth}_options"
|
|
242
|
+
send msg, opts, options if respond_to? msg
|
|
243
|
+
when Module
|
|
244
|
+
recv = mod_or_meth
|
|
245
|
+
next unless recv.respond_to? :minitest_plugin_options
|
|
246
|
+
recv.minitest_plugin_options opts, options
|
|
247
|
+
else
|
|
248
|
+
raise ArgumentError, "plugin is %p, but it must be a symbol, string or module" % [mod_or_meth]
|
|
249
|
+
end
|
|
235
250
|
end
|
|
236
251
|
end
|
|
237
252
|
|
|
@@ -255,12 +270,98 @@ module Minitest
|
|
|
255
270
|
end
|
|
256
271
|
|
|
257
272
|
options[:args] = orig_args.map { |s|
|
|
258
|
-
s
|
|
273
|
+
s.match?(/[\s|&<>$()]/) ? s.inspect : s
|
|
259
274
|
}.join " "
|
|
260
275
|
|
|
261
276
|
options
|
|
262
277
|
end
|
|
263
278
|
|
|
279
|
+
##
|
|
280
|
+
# This is the top-level run method. Everything starts from here. It
|
|
281
|
+
# tells each Runnable sub-class to run, and each of those are
|
|
282
|
+
# responsible for doing whatever they do.
|
|
283
|
+
#
|
|
284
|
+
# The overall structure of a run looks like this:
|
|
285
|
+
#
|
|
286
|
+
# [Minitest.load_plugins] optional, called by user, or require what you want
|
|
287
|
+
# Minitest.autorun
|
|
288
|
+
# Minitest.run(args)
|
|
289
|
+
# Minitest.process_args
|
|
290
|
+
# Minitest.init_plugins
|
|
291
|
+
# Minitest.run_all_suites(reporter, options)
|
|
292
|
+
# Runnable.runnables.each |runnable_klass|
|
|
293
|
+
# runnable_klass.run_suite(reporter, options)
|
|
294
|
+
# filtered_methods = runnable_klass.filter_runnable_methods options
|
|
295
|
+
# filtered_methods.each |runnable_method|
|
|
296
|
+
# runnable_klass.run(self, runnable_method, reporter)
|
|
297
|
+
# runnable_klass.new(runnable_method).run
|
|
298
|
+
|
|
299
|
+
def self.run args = []
|
|
300
|
+
options = process_args args
|
|
301
|
+
|
|
302
|
+
Minitest.seed = options[:seed]
|
|
303
|
+
srand Minitest.seed
|
|
304
|
+
|
|
305
|
+
reporter = CompositeReporter.new
|
|
306
|
+
reporter << SummaryReporter.new(options[:io], options)
|
|
307
|
+
reporter << ProgressReporter.new(options[:io], options) unless options[:quiet]
|
|
308
|
+
|
|
309
|
+
self.reporter = reporter # this makes it available to plugins
|
|
310
|
+
self.init_plugins options
|
|
311
|
+
self.reporter = nil # runnables shouldn't depend on the reporter, ever
|
|
312
|
+
|
|
313
|
+
self.parallel_executor.start if parallel_executor.respond_to? :start
|
|
314
|
+
reporter.start
|
|
315
|
+
begin
|
|
316
|
+
run_all_suites reporter, options
|
|
317
|
+
finished = true
|
|
318
|
+
rescue Interrupt
|
|
319
|
+
warn "Interrupted. Exiting..."
|
|
320
|
+
end
|
|
321
|
+
self.parallel_executor.shutdown if parallel_executor.respond_to? :shutdown
|
|
322
|
+
|
|
323
|
+
# might have been removed/replaced during init_plugins:
|
|
324
|
+
summary = reporter.reporters.grep(SummaryReporter).first
|
|
325
|
+
|
|
326
|
+
reporter.report
|
|
327
|
+
|
|
328
|
+
return empty_run! options if finished && summary && summary.count == 0
|
|
329
|
+
finished and reporter.passed?
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def self.empty_run! options # :nodoc:
|
|
333
|
+
filter = options[:include]
|
|
334
|
+
return true unless filter # no filter, but nothing ran == success
|
|
335
|
+
|
|
336
|
+
warn "Nothing ran for filter: %s" % [filter]
|
|
337
|
+
|
|
338
|
+
require "did_you_mean" # soft dependency, punt if it doesn't load
|
|
339
|
+
|
|
340
|
+
ms = Runnable.runnables.flat_map(&:runnable_methods)
|
|
341
|
+
cs = DidYouMean::SpellChecker.new(dictionary: ms).correct filter
|
|
342
|
+
|
|
343
|
+
warn DidYouMean::Formatter.message_for cs unless cs.empty?
|
|
344
|
+
rescue LoadError
|
|
345
|
+
# do nothing
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
##
|
|
349
|
+
# Internal run method. Responsible for telling all Runnable
|
|
350
|
+
# sub-classes to run.
|
|
351
|
+
|
|
352
|
+
def self.run_all_suites reporter, options
|
|
353
|
+
suites = Runnable.runnables.shuffle
|
|
354
|
+
parallel, serial = suites.partition { |s| s.run_order == :parallel }
|
|
355
|
+
|
|
356
|
+
# If we run the parallel tests before the serial tests, the parallel tests
|
|
357
|
+
# could run in parallel with the serial tests. This would be bad because
|
|
358
|
+
# the serial tests won't lock around Reporter#record. Run the serial tests
|
|
359
|
+
# first, so that after they complete, the parallel tests will lock when
|
|
360
|
+
# recording results.
|
|
361
|
+
serial.map { |suite| suite.run_suite reporter, options } +
|
|
362
|
+
parallel.map { |suite| suite.run_suite reporter, options }
|
|
363
|
+
end
|
|
364
|
+
|
|
264
365
|
def self.filter_backtrace bt # :nodoc:
|
|
265
366
|
result = backtrace_filter.filter bt
|
|
266
367
|
result = bt.dup if result.empty?
|
|
@@ -325,31 +426,51 @@ module Minitest
|
|
|
325
426
|
|
|
326
427
|
reset
|
|
327
428
|
|
|
429
|
+
##
|
|
430
|
+
# Returns an array of filtered +runnable_methods+. Uses
|
|
431
|
+
# options[:include] (--include arguments) and options[:exclude]
|
|
432
|
+
# (--exclude arguments) values to filter.
|
|
433
|
+
|
|
434
|
+
def self.filter_runnable_methods options={}
|
|
435
|
+
pos = options[:include]
|
|
436
|
+
neg = options[:exclude]
|
|
437
|
+
|
|
438
|
+
pos = Regexp.new $1 if pos.kind_of?(String) && pos =~ %r%/(.*)/%
|
|
439
|
+
neg = Regexp.new $1 if neg.kind_of?(String) && neg =~ %r%/(.*)/%
|
|
440
|
+
|
|
441
|
+
# at most 1-2% slower than a 1-pass version, stop optimizing this
|
|
442
|
+
self.runnable_methods
|
|
443
|
+
.select { |m| !pos || pos === m || pos === "#{self}##{m}" }
|
|
444
|
+
.reject { |m| neg && (neg === m || neg === "#{self}##{m}") }
|
|
445
|
+
end
|
|
446
|
+
|
|
328
447
|
##
|
|
329
448
|
# Responsible for running all runnable methods in a given class,
|
|
330
449
|
# each in its own instance. Each instance is passed to the
|
|
331
450
|
# reporter to record.
|
|
332
451
|
|
|
333
|
-
def
|
|
334
|
-
|
|
335
|
-
filter = Regexp.new $1 if filter.is_a?(String) && filter =~ %r%/(.*)/%
|
|
452
|
+
def Runnable.run_suite reporter, options = {}
|
|
453
|
+
filtered_methods = filter_runnable_methods options
|
|
336
454
|
|
|
337
|
-
|
|
338
|
-
filter === m || filter === "#{self}##{m}"
|
|
339
|
-
}
|
|
455
|
+
return if filtered_methods.empty?
|
|
340
456
|
|
|
341
|
-
|
|
342
|
-
exclude = Regexp.new $1 if exclude =~ %r%/(.*)/%
|
|
457
|
+
t0 = name = nil
|
|
343
458
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
459
|
+
@_info_handler = lambda do
|
|
460
|
+
unless reporter.passed? then
|
|
461
|
+
warn "Current results:"
|
|
462
|
+
warn reporter.reporters.grep(SummaryReporter).first
|
|
463
|
+
end
|
|
347
464
|
|
|
348
|
-
|
|
465
|
+
warn "Current: %s#%s %.2fs" % [self, name, Minitest.clock_time - t0]
|
|
466
|
+
end
|
|
349
467
|
|
|
350
|
-
with_info_handler
|
|
468
|
+
with_info_handler do
|
|
351
469
|
filtered_methods.each do |method_name|
|
|
352
|
-
|
|
470
|
+
name = method_name
|
|
471
|
+
t0 = Minitest.clock_time
|
|
472
|
+
|
|
473
|
+
run self, method_name, reporter
|
|
353
474
|
end
|
|
354
475
|
end
|
|
355
476
|
end
|
|
@@ -360,22 +481,21 @@ module Minitest
|
|
|
360
481
|
# that subclasses can specialize the running of an individual
|
|
361
482
|
# test. See Minitest::ParallelTest::ClassMethods for an example.
|
|
362
483
|
|
|
363
|
-
def
|
|
484
|
+
def Runnable.run klass, method_name, reporter
|
|
364
485
|
reporter.prerecord klass, method_name
|
|
365
|
-
reporter.record
|
|
486
|
+
reporter.record klass.new(method_name).run
|
|
366
487
|
end
|
|
367
488
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
end
|
|
376
|
-
end
|
|
489
|
+
##
|
|
490
|
+
# Defines the order to run tests (:random by default). Override
|
|
491
|
+
# this or use a convenience method to change it for your tests.
|
|
492
|
+
|
|
493
|
+
def self.run_order
|
|
494
|
+
:random
|
|
495
|
+
end
|
|
377
496
|
|
|
378
|
-
|
|
497
|
+
def self.with_info_handler _reporter=nil, &block # :nodoc:
|
|
498
|
+
on_signal ::Minitest.info_signal, @_info_handler, &block
|
|
379
499
|
end
|
|
380
500
|
|
|
381
501
|
SIGNALS = Signal.list # :nodoc:
|
|
@@ -408,22 +528,6 @@ module Minitest
|
|
|
408
528
|
@@runnables
|
|
409
529
|
end
|
|
410
530
|
|
|
411
|
-
@@marshal_dump_warned = false
|
|
412
|
-
|
|
413
|
-
def marshal_dump # :nodoc:
|
|
414
|
-
unless @@marshal_dump_warned then
|
|
415
|
-
warn ["Minitest::Runnable#marshal_dump is deprecated.",
|
|
416
|
-
"You might be violating internals. From", caller.first].join " "
|
|
417
|
-
@@marshal_dump_warned = true
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
[self.name, self.failures, self.assertions, self.time]
|
|
421
|
-
end
|
|
422
|
-
|
|
423
|
-
def marshal_load ary # :nodoc:
|
|
424
|
-
self.name, self.failures, self.assertions, self.time = ary
|
|
425
|
-
end
|
|
426
|
-
|
|
427
531
|
def failure # :nodoc:
|
|
428
532
|
self.failures.first
|
|
429
533
|
end
|
|
@@ -432,6 +536,31 @@ module Minitest
|
|
|
432
536
|
self.name = name
|
|
433
537
|
self.failures = []
|
|
434
538
|
self.assertions = 0
|
|
539
|
+
# lazy initializer for metadata
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
##
|
|
543
|
+
# Metadata you attach to the test results that get sent to the reporter.
|
|
544
|
+
#
|
|
545
|
+
# Lazily initializes to a hash, to keep memory down.
|
|
546
|
+
#
|
|
547
|
+
# NOTE: this data *must* be plain (read: marshal-able) data!
|
|
548
|
+
# Hashes! Arrays! Strings!
|
|
549
|
+
|
|
550
|
+
def metadata
|
|
551
|
+
@metadata ||= {}
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
##
|
|
555
|
+
# Sets metadata, mainly used for +Result.from+.
|
|
556
|
+
|
|
557
|
+
attr_writer :metadata
|
|
558
|
+
|
|
559
|
+
##
|
|
560
|
+
# Returns true if metadata exists.
|
|
561
|
+
|
|
562
|
+
def metadata?
|
|
563
|
+
defined? @metadata
|
|
435
564
|
end
|
|
436
565
|
|
|
437
566
|
##
|
|
@@ -466,7 +595,7 @@ module Minitest
|
|
|
466
595
|
def skipped?
|
|
467
596
|
raise NotImplementedError, "subclass responsibility"
|
|
468
597
|
end
|
|
469
|
-
end
|
|
598
|
+
end # Runnable
|
|
470
599
|
|
|
471
600
|
##
|
|
472
601
|
# Shared code for anything that can get passed to a Reporter. See
|
|
@@ -483,12 +612,14 @@ module Minitest
|
|
|
483
612
|
not self.failure
|
|
484
613
|
end
|
|
485
614
|
|
|
615
|
+
BASE_DIR = "#{Dir.pwd}/" # :nodoc:
|
|
616
|
+
|
|
486
617
|
##
|
|
487
618
|
# The location identifier of this test. Depends on a method
|
|
488
619
|
# existing called class_name.
|
|
489
620
|
|
|
490
621
|
def location
|
|
491
|
-
loc = " [#{self.failure.location}]" unless passed? or error?
|
|
622
|
+
loc = " [#{self.failure.location.delete_prefix BASE_DIR}]" unless passed? or error?
|
|
492
623
|
"#{self.class_name}##{self.name}#{loc}"
|
|
493
624
|
end
|
|
494
625
|
|
|
@@ -514,9 +645,9 @@ module Minitest
|
|
|
514
645
|
# Did this run error?
|
|
515
646
|
|
|
516
647
|
def error?
|
|
517
|
-
self.failures.any?
|
|
648
|
+
self.failures.any? UnexpectedError
|
|
518
649
|
end
|
|
519
|
-
end
|
|
650
|
+
end # Reportable
|
|
520
651
|
|
|
521
652
|
##
|
|
522
653
|
# This represents a test result in a clean way that can be
|
|
@@ -528,9 +659,6 @@ module Minitest
|
|
|
528
659
|
class Result < Runnable
|
|
529
660
|
include Minitest::Reportable
|
|
530
661
|
|
|
531
|
-
undef_method :marshal_dump
|
|
532
|
-
undef_method :marshal_load
|
|
533
|
-
|
|
534
662
|
##
|
|
535
663
|
# The class name of the test result.
|
|
536
664
|
|
|
@@ -552,6 +680,7 @@ module Minitest
|
|
|
552
680
|
r.assertions = o.assertions
|
|
553
681
|
r.failures = o.failures.dup
|
|
554
682
|
r.time = o.time
|
|
683
|
+
r.metadata = o.metadata if o.metadata?
|
|
555
684
|
|
|
556
685
|
r.source_location = o.method(o.name).source_location rescue ["unknown", -1]
|
|
557
686
|
|
|
@@ -569,14 +698,17 @@ module Minitest
|
|
|
569
698
|
"#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n"
|
|
570
699
|
}.join "\n"
|
|
571
700
|
end
|
|
572
|
-
end
|
|
701
|
+
end # Result
|
|
573
702
|
|
|
574
703
|
##
|
|
575
704
|
# Defines the API for Reporters. Subclass this and override whatever
|
|
576
705
|
# you want. Go nuts.
|
|
577
706
|
|
|
578
707
|
class AbstractReporter
|
|
579
|
-
|
|
708
|
+
|
|
709
|
+
def initialize # :nodoc:
|
|
710
|
+
@mutex = Mutex.new
|
|
711
|
+
end
|
|
580
712
|
|
|
581
713
|
##
|
|
582
714
|
# Starts reporting on the run.
|
|
@@ -612,7 +744,11 @@ module Minitest
|
|
|
612
744
|
def passed?
|
|
613
745
|
true
|
|
614
746
|
end
|
|
615
|
-
|
|
747
|
+
|
|
748
|
+
def synchronize &block # :nodoc:
|
|
749
|
+
@mutex.synchronize(&block)
|
|
750
|
+
end
|
|
751
|
+
end # AbstractReportera
|
|
616
752
|
|
|
617
753
|
class Reporter < AbstractReporter # :nodoc:
|
|
618
754
|
##
|
|
@@ -641,11 +777,11 @@ module Minitest
|
|
|
641
777
|
# own.
|
|
642
778
|
|
|
643
779
|
class ProgressReporter < Reporter
|
|
644
|
-
def prerecord klass, name
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
780
|
+
def prerecord klass, name # :nodoc:
|
|
781
|
+
return unless options[:verbose]
|
|
782
|
+
|
|
783
|
+
io.print "%s#%s = " % [klass.name, name]
|
|
784
|
+
io.flush
|
|
649
785
|
end
|
|
650
786
|
|
|
651
787
|
def record result # :nodoc:
|
|
@@ -715,6 +851,11 @@ module Minitest
|
|
|
715
851
|
|
|
716
852
|
attr_accessor :errors
|
|
717
853
|
|
|
854
|
+
##
|
|
855
|
+
# Total number of tests that warned.
|
|
856
|
+
|
|
857
|
+
attr_accessor :warnings
|
|
858
|
+
|
|
718
859
|
##
|
|
719
860
|
# Total number of tests that where skipped.
|
|
720
861
|
|
|
@@ -730,6 +871,7 @@ module Minitest
|
|
|
730
871
|
self.total_time = nil
|
|
731
872
|
self.failures = nil
|
|
732
873
|
self.errors = nil
|
|
874
|
+
self.warnings = nil
|
|
733
875
|
self.skips = nil
|
|
734
876
|
end
|
|
735
877
|
|
|
@@ -758,9 +900,10 @@ module Minitest
|
|
|
758
900
|
self.total_time = Minitest.clock_time - start_time
|
|
759
901
|
self.failures = aggregate[Assertion].size
|
|
760
902
|
self.errors = aggregate[UnexpectedError].size
|
|
903
|
+
self.warnings = aggregate[UnexpectedWarning].size
|
|
761
904
|
self.skips = aggregate[Skip].size
|
|
762
905
|
end
|
|
763
|
-
end
|
|
906
|
+
end # StatisticsReporter
|
|
764
907
|
|
|
765
908
|
##
|
|
766
909
|
# A reporter that prints the header, summary, and failure details at
|
|
@@ -772,10 +915,8 @@ module Minitest
|
|
|
772
915
|
# own.
|
|
773
916
|
|
|
774
917
|
class SummaryReporter < StatisticsReporter
|
|
775
|
-
# :
|
|
776
|
-
attr_accessor :
|
|
777
|
-
attr_accessor :old_sync
|
|
778
|
-
# :startdoc:
|
|
918
|
+
attr_accessor :sync # :nodoc:
|
|
919
|
+
attr_accessor :old_sync # :nodoc:
|
|
779
920
|
|
|
780
921
|
def start # :nodoc:
|
|
781
922
|
super
|
|
@@ -785,7 +926,7 @@ module Minitest
|
|
|
785
926
|
io.puts "# Running:"
|
|
786
927
|
io.puts
|
|
787
928
|
|
|
788
|
-
self.sync = io.respond_to? :"sync="
|
|
929
|
+
self.sync = io.respond_to? :"sync="
|
|
789
930
|
self.old_sync, io.sync = io.sync, true if self.sync
|
|
790
931
|
end
|
|
791
932
|
|
|
@@ -823,28 +964,24 @@ module Minitest
|
|
|
823
964
|
end
|
|
824
965
|
|
|
825
966
|
def to_s # :nodoc:
|
|
826
|
-
aggregated_results(StringIO.new(
|
|
967
|
+
aggregated_results(StringIO.new("".b)).string
|
|
827
968
|
end
|
|
828
969
|
|
|
829
970
|
def summary # :nodoc:
|
|
830
|
-
extra =
|
|
971
|
+
extra = []
|
|
972
|
+
|
|
973
|
+
extra << ", %d warnings" % [warnings] if options[:Werror]
|
|
831
974
|
|
|
832
|
-
extra
|
|
975
|
+
extra << "\n\nYou have skipped tests. Run with --verbose for details." if
|
|
833
976
|
results.any?(&:skipped?) unless
|
|
834
|
-
options[:verbose]
|
|
977
|
+
options[:verbose] or
|
|
978
|
+
options[:show_skips] or
|
|
979
|
+
ENV["MT_NO_SKIP_MSG"]
|
|
835
980
|
|
|
836
981
|
"%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
|
|
837
|
-
[count, assertions, failures, errors, skips, extra]
|
|
982
|
+
[count, assertions, failures, errors, skips, extra.join]
|
|
838
983
|
end
|
|
839
|
-
|
|
840
|
-
private
|
|
841
|
-
|
|
842
|
-
if '<3'.respond_to? :b
|
|
843
|
-
def binary_string; ''.b; end
|
|
844
|
-
else
|
|
845
|
-
def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end
|
|
846
|
-
end
|
|
847
|
-
end
|
|
984
|
+
end # SummaryReporter
|
|
848
985
|
|
|
849
986
|
##
|
|
850
987
|
# Dispatch to multiple reporters as one.
|
|
@@ -881,8 +1018,7 @@ module Minitest
|
|
|
881
1018
|
|
|
882
1019
|
def prerecord klass, name # :nodoc:
|
|
883
1020
|
self.reporters.each do |reporter|
|
|
884
|
-
|
|
885
|
-
reporter.prerecord klass, name if reporter.respond_to? :prerecord
|
|
1021
|
+
reporter.prerecord klass, name
|
|
886
1022
|
end
|
|
887
1023
|
end
|
|
888
1024
|
|
|
@@ -895,12 +1031,14 @@ module Minitest
|
|
|
895
1031
|
def report # :nodoc:
|
|
896
1032
|
self.reporters.each(&:report)
|
|
897
1033
|
end
|
|
898
|
-
end
|
|
1034
|
+
end # CompositeReporter
|
|
899
1035
|
|
|
900
1036
|
##
|
|
901
1037
|
# Represents run failures.
|
|
902
1038
|
|
|
903
1039
|
class Assertion < Exception
|
|
1040
|
+
RE = /in [`'](?:[^']+[#.])?(?:assert|refute|flunk|pass|fail|raise|must|wont)/ # :nodoc:
|
|
1041
|
+
|
|
904
1042
|
def error # :nodoc:
|
|
905
1043
|
self
|
|
906
1044
|
end
|
|
@@ -909,12 +1047,11 @@ module Minitest
|
|
|
909
1047
|
# Where was this run before an assertion was raised?
|
|
910
1048
|
|
|
911
1049
|
def location
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
last_before_assertion.sub(/:in .*$/, "")
|
|
1050
|
+
bt = Minitest.filter_backtrace self.backtrace
|
|
1051
|
+
idx = bt.rindex { |s| s.match? RE } || -1 # fall back to first item
|
|
1052
|
+
loc = bt[idx+1] || bt.last || "unknown:-1"
|
|
1053
|
+
|
|
1054
|
+
loc.sub(/:in .*$/, "")
|
|
918
1055
|
end
|
|
919
1056
|
|
|
920
1057
|
def result_code # :nodoc:
|
|
@@ -939,11 +1076,21 @@ module Minitest
|
|
|
939
1076
|
# Assertion wrapping an unexpected error that was raised during a run.
|
|
940
1077
|
|
|
941
1078
|
class UnexpectedError < Assertion
|
|
1079
|
+
include Minitest::Compress
|
|
1080
|
+
|
|
942
1081
|
# TODO: figure out how to use `cause` instead
|
|
943
1082
|
attr_accessor :error # :nodoc:
|
|
944
1083
|
|
|
945
1084
|
def initialize error # :nodoc:
|
|
946
1085
|
super "Unexpected exception"
|
|
1086
|
+
|
|
1087
|
+
if SystemStackError === error then
|
|
1088
|
+
bt = error.backtrace
|
|
1089
|
+
new_bt = compress bt
|
|
1090
|
+
error = error.exception "#{bt.size} -> #{new_bt.size}"
|
|
1091
|
+
error.set_backtrace new_bt
|
|
1092
|
+
end
|
|
1093
|
+
|
|
947
1094
|
self.error = error
|
|
948
1095
|
end
|
|
949
1096
|
|
|
@@ -951,8 +1098,11 @@ module Minitest
|
|
|
951
1098
|
self.error.backtrace
|
|
952
1099
|
end
|
|
953
1100
|
|
|
1101
|
+
BASE_RE = %r%#{Regexp.escape Dir.pwd}/% # :nodoc:
|
|
1102
|
+
|
|
954
1103
|
def message # :nodoc:
|
|
955
|
-
bt = Minitest.filter_backtrace(self.backtrace).join
|
|
1104
|
+
bt = Minitest.filter_backtrace(self.backtrace).join("\n ")
|
|
1105
|
+
.gsub(BASE_RE, "")
|
|
956
1106
|
"#{self.error.class}: #{self.error.message}\n #{bt}"
|
|
957
1107
|
end
|
|
958
1108
|
|
|
@@ -961,6 +1111,15 @@ module Minitest
|
|
|
961
1111
|
end
|
|
962
1112
|
end
|
|
963
1113
|
|
|
1114
|
+
##
|
|
1115
|
+
# Assertion raised on warning when running in -Werror mode.
|
|
1116
|
+
|
|
1117
|
+
class UnexpectedWarning < Assertion
|
|
1118
|
+
def result_label # :nodoc:
|
|
1119
|
+
"Warning"
|
|
1120
|
+
end
|
|
1121
|
+
end
|
|
1122
|
+
|
|
964
1123
|
##
|
|
965
1124
|
# Provides a simple set of guards that you can use in your tests
|
|
966
1125
|
# to skip execution if it is not applicable. These methods are
|
|
@@ -985,45 +1144,25 @@ module Minitest
|
|
|
985
1144
|
"java" == platform
|
|
986
1145
|
end
|
|
987
1146
|
|
|
988
|
-
##
|
|
989
|
-
# Is this running on maglev?
|
|
990
|
-
|
|
991
|
-
def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
|
992
|
-
where = Minitest.filter_backtrace(caller).first
|
|
993
|
-
where = where.split(/:in /, 2).first # clean up noise
|
|
994
|
-
warn "DEPRECATED: `maglev?` called from #{where}. This will fail in Minitest 6."
|
|
995
|
-
"maglev" == platform
|
|
996
|
-
end
|
|
997
|
-
|
|
998
1147
|
##
|
|
999
1148
|
# Is this running on mri?
|
|
1000
1149
|
|
|
1001
1150
|
def mri? platform = RUBY_DESCRIPTION
|
|
1002
|
-
|
|
1151
|
+
platform.start_with? "ruby"
|
|
1003
1152
|
end
|
|
1004
1153
|
|
|
1005
1154
|
##
|
|
1006
1155
|
# Is this running on macOS?
|
|
1007
1156
|
|
|
1008
1157
|
def osx? platform = RUBY_PLATFORM
|
|
1009
|
-
|
|
1010
|
-
end
|
|
1011
|
-
|
|
1012
|
-
##
|
|
1013
|
-
# Is this running on rubinius?
|
|
1014
|
-
|
|
1015
|
-
def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
|
1016
|
-
where = Minitest.filter_backtrace(caller).first
|
|
1017
|
-
where = where.split(/:in /, 2).first # clean up noise
|
|
1018
|
-
warn "DEPRECATED: `rubinius?` called from #{where}. This will fail in Minitest 6."
|
|
1019
|
-
"rbx" == platform
|
|
1158
|
+
platform.include? "darwin"
|
|
1020
1159
|
end
|
|
1021
1160
|
|
|
1022
1161
|
##
|
|
1023
1162
|
# Is this running on windows?
|
|
1024
1163
|
|
|
1025
1164
|
def windows? platform = RUBY_PLATFORM
|
|
1026
|
-
/mswin|mingw
|
|
1165
|
+
/mswin|mingw/.match? platform
|
|
1027
1166
|
end
|
|
1028
1167
|
end
|
|
1029
1168
|
|
|
@@ -1034,7 +1173,16 @@ module Minitest
|
|
|
1034
1173
|
|
|
1035
1174
|
class BacktraceFilter
|
|
1036
1175
|
|
|
1037
|
-
MT_RE = %r%lib/minitest%
|
|
1176
|
+
MT_RE = %r%lib/minitest|internal:warning% # :nodoc:
|
|
1177
|
+
|
|
1178
|
+
##
|
|
1179
|
+
# The regular expression to use to filter backtraces. Defaults to +MT_RE+.
|
|
1180
|
+
|
|
1181
|
+
attr_accessor :regexp
|
|
1182
|
+
|
|
1183
|
+
def initialize regexp = MT_RE # :nodoc:
|
|
1184
|
+
self.regexp = regexp
|
|
1185
|
+
end
|
|
1038
1186
|
|
|
1039
1187
|
##
|
|
1040
1188
|
# Filter +bt+ to something useful. Returns the whole thing if
|
|
@@ -1045,9 +1193,9 @@ module Minitest
|
|
|
1045
1193
|
|
|
1046
1194
|
return bt.dup if $DEBUG || ENV["MT_DEBUG"]
|
|
1047
1195
|
|
|
1048
|
-
new_bt = bt.take_while { |line| line
|
|
1049
|
-
new_bt = bt.select { |line| line
|
|
1050
|
-
new_bt = bt.dup
|
|
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?
|
|
1051
1199
|
|
|
1052
1200
|
new_bt
|
|
1053
1201
|
end
|
|
@@ -1055,12 +1203,6 @@ module Minitest
|
|
|
1055
1203
|
|
|
1056
1204
|
self.backtrace_filter = BacktraceFilter.new
|
|
1057
1205
|
|
|
1058
|
-
def self.run_one_method klass, method_name # :nodoc:
|
|
1059
|
-
result = klass.new(method_name).run
|
|
1060
|
-
raise "#{klass}#run _must_ return a Result" unless Result === result
|
|
1061
|
-
result
|
|
1062
|
-
end
|
|
1063
|
-
|
|
1064
1206
|
# :stopdoc:
|
|
1065
1207
|
|
|
1066
1208
|
if defined? Process::CLOCK_MONOTONIC # :nodoc:
|
|
@@ -1083,4 +1225,8 @@ module Minitest
|
|
|
1083
1225
|
# :startdoc:
|
|
1084
1226
|
end
|
|
1085
1227
|
|
|
1086
|
-
|
|
1228
|
+
require_relative "minitest/test"
|
|
1229
|
+
if ENV["MINITEST_SERVER"] then
|
|
1230
|
+
require_relative "minitest/server_plugin"
|
|
1231
|
+
Minitest.register_plugin :server
|
|
1232
|
+
end
|