mega-sharp-tool 0.0.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.
- checksums.yaml +7 -0
- data/mega-sharp-tool.gemspec +12 -0
- data/minitest-6.0.6/History.rdoc +1860 -0
- data/minitest-6.0.6/Manifest.txt +41 -0
- data/minitest-6.0.6/README.rdoc +763 -0
- data/minitest-6.0.6/Rakefile +89 -0
- data/minitest-6.0.6/bin/minitest +5 -0
- data/minitest-6.0.6/design_rationale.rb +54 -0
- data/minitest-6.0.6/lib/hoe/minitest.rb +30 -0
- data/minitest-6.0.6/lib/minitest/assertions.rb +821 -0
- data/minitest-6.0.6/lib/minitest/autorun.rb +5 -0
- data/minitest-6.0.6/lib/minitest/benchmark.rb +452 -0
- data/minitest-6.0.6/lib/minitest/bisect.rb +304 -0
- data/minitest-6.0.6/lib/minitest/complete.rb +56 -0
- data/minitest-6.0.6/lib/minitest/compress.rb +94 -0
- data/minitest-6.0.6/lib/minitest/error_on_warning.rb +11 -0
- data/minitest-6.0.6/lib/minitest/expectations.rb +321 -0
- data/minitest-6.0.6/lib/minitest/find_minimal_combination.rb +127 -0
- data/minitest-6.0.6/lib/minitest/hell.rb +11 -0
- data/minitest-6.0.6/lib/minitest/manual_plugins.rb +4 -0
- data/minitest-6.0.6/lib/minitest/parallel.rb +72 -0
- data/minitest-6.0.6/lib/minitest/path_expander.rb +432 -0
- data/minitest-6.0.6/lib/minitest/pride.rb +4 -0
- data/minitest-6.0.6/lib/minitest/pride_plugin.rb +135 -0
- data/minitest-6.0.6/lib/minitest/server.rb +49 -0
- data/minitest-6.0.6/lib/minitest/server_plugin.rb +88 -0
- data/minitest-6.0.6/lib/minitest/spec.rb +324 -0
- data/minitest-6.0.6/lib/minitest/sprint.rb +105 -0
- data/minitest-6.0.6/lib/minitest/sprint_plugin.rb +39 -0
- data/minitest-6.0.6/lib/minitest/test.rb +232 -0
- data/minitest-6.0.6/lib/minitest/test_task.rb +331 -0
- data/minitest-6.0.6/lib/minitest.rb +1232 -0
- data/minitest-6.0.6/test/minitest/metametameta.rb +150 -0
- data/minitest-6.0.6/test/minitest/test_bisect.rb +249 -0
- data/minitest-6.0.6/test/minitest/test_find_minimal_combination.rb +138 -0
- data/minitest-6.0.6/test/minitest/test_minitest_assertions.rb +1729 -0
- data/minitest-6.0.6/test/minitest/test_minitest_benchmark.rb +151 -0
- data/minitest-6.0.6/test/minitest/test_minitest_reporter.rb +437 -0
- data/minitest-6.0.6/test/minitest/test_minitest_spec.rb +1095 -0
- data/minitest-6.0.6/test/minitest/test_minitest_test.rb +1295 -0
- data/minitest-6.0.6/test/minitest/test_minitest_test_task.rb +57 -0
- data/minitest-6.0.6/test/minitest/test_path_expander.rb +229 -0
- data/minitest-6.0.6/test/minitest/test_server.rb +146 -0
- metadata +83 -0
|
@@ -0,0 +1,1232 @@
|
|
|
1
|
+
require "optparse"
|
|
2
|
+
require "stringio"
|
|
3
|
+
require "etc"
|
|
4
|
+
|
|
5
|
+
require_relative "minitest/parallel"
|
|
6
|
+
require_relative "minitest/compress"
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# The top-level namespace for Minitest. Also the location of the main
|
|
10
|
+
# runtime. See +Minitest.run+ for more information.
|
|
11
|
+
|
|
12
|
+
module Minitest
|
|
13
|
+
VERSION = "6.0.6" # :nodoc:
|
|
14
|
+
|
|
15
|
+
@@installed_at_exit ||= false
|
|
16
|
+
@@after_run = []
|
|
17
|
+
@extensions = []
|
|
18
|
+
|
|
19
|
+
def self.cattr_accessor name # :nodoc:
|
|
20
|
+
(class << self; self; end).attr_accessor name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# The random seed used for this run. This is used to srand at the
|
|
25
|
+
# start of the run and between each +Runnable.run+.
|
|
26
|
+
#
|
|
27
|
+
# Set via Minitest.run after processing args.
|
|
28
|
+
|
|
29
|
+
cattr_accessor :seed
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Parallel test executor
|
|
33
|
+
|
|
34
|
+
cattr_accessor :parallel_executor
|
|
35
|
+
|
|
36
|
+
n_threads = (ENV["MT_CPU"] || Etc.nprocessors).to_i
|
|
37
|
+
|
|
38
|
+
self.parallel_executor = Parallel::Executor.new n_threads if n_threads > 1
|
|
39
|
+
|
|
40
|
+
##
|
|
41
|
+
# Filter object for backtraces.
|
|
42
|
+
|
|
43
|
+
cattr_accessor :backtrace_filter
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# Reporter object to be used for all runs.
|
|
47
|
+
#
|
|
48
|
+
# NOTE: This accessor is only available during setup, not during runs.
|
|
49
|
+
|
|
50
|
+
cattr_accessor :reporter
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Names of known extension plugins.
|
|
54
|
+
|
|
55
|
+
cattr_accessor :extensions
|
|
56
|
+
|
|
57
|
+
##
|
|
58
|
+
# The signal to use for dumping information to STDERR. Defaults to "INFO".
|
|
59
|
+
|
|
60
|
+
cattr_accessor :info_signal
|
|
61
|
+
self.info_signal = "INFO"
|
|
62
|
+
|
|
63
|
+
cattr_accessor :allow_fork
|
|
64
|
+
self.allow_fork = false
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# Registers Minitest to run at process exit
|
|
68
|
+
|
|
69
|
+
def self.autorun
|
|
70
|
+
Warning[:deprecated] = true
|
|
71
|
+
|
|
72
|
+
at_exit {
|
|
73
|
+
next if $! and not ($!.kind_of? SystemExit and $!.success?)
|
|
74
|
+
|
|
75
|
+
exit_code = nil
|
|
76
|
+
|
|
77
|
+
pid = Process.pid
|
|
78
|
+
at_exit {
|
|
79
|
+
next if !Minitest.allow_fork && Process.pid != pid
|
|
80
|
+
@@after_run.reverse_each(&:call)
|
|
81
|
+
exit exit_code || false
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
exit_code = Minitest.run ARGV
|
|
85
|
+
} unless @@installed_at_exit
|
|
86
|
+
@@installed_at_exit = true
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
##
|
|
90
|
+
# A simple hook allowing you to run a block of code after everything
|
|
91
|
+
# is done running. Eg:
|
|
92
|
+
#
|
|
93
|
+
# Minitest.after_run { p $debugging_info }
|
|
94
|
+
|
|
95
|
+
def self.after_run &block
|
|
96
|
+
@@after_run << block
|
|
97
|
+
end
|
|
98
|
+
|
|
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
|
|
107
|
+
end
|
|
108
|
+
end
|
|
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
|
+
|
|
118
|
+
def self.load_plugins # :nodoc:
|
|
119
|
+
return unless defined? Gem
|
|
120
|
+
|
|
121
|
+
seen = {}
|
|
122
|
+
|
|
123
|
+
Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
|
|
124
|
+
name = File.basename plugin_path, "_plugin.rb"
|
|
125
|
+
|
|
126
|
+
next if seen[name]
|
|
127
|
+
seen[name] = true
|
|
128
|
+
|
|
129
|
+
require plugin_path
|
|
130
|
+
self.extensions << name
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
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
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def self.process_args args = [] # :nodoc:
|
|
153
|
+
options = {
|
|
154
|
+
:io => $stdout,
|
|
155
|
+
}
|
|
156
|
+
orig_args = args.dup
|
|
157
|
+
|
|
158
|
+
warn "--no-plugins is a no-op" if args.delete "--no-plugins" # TODO: remove me! when?
|
|
159
|
+
|
|
160
|
+
OptionParser.new do |opts|
|
|
161
|
+
opts.program_name = "minitest"
|
|
162
|
+
opts.version = Minitest::VERSION
|
|
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
|
+
|
|
170
|
+
opts.on "-h", "--help", "Display this help." do
|
|
171
|
+
puts opts
|
|
172
|
+
exit! true
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
opts.on "-V", "--version", "Display the version." do
|
|
176
|
+
puts "#{opts.program_name} #{Minitest::VERSION}"
|
|
177
|
+
exit! true
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
desc = "Sets random seed. Also via env, eg: SEED=42"
|
|
181
|
+
opts.on "-s", "--seed SEED", Integer, desc do |m|
|
|
182
|
+
options[:seed] = m
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
opts.on "-v", "--verbose", "Verbose. Print each name as they run." do
|
|
186
|
+
options[:verbose] = true
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
opts.on "-q", "--quiet", "Quiet. Show no dots while processing files." do
|
|
190
|
+
options[:quiet] = true
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
opts.on "--show-skips", "Show skipped at the end of run." do
|
|
194
|
+
options[:show_skips] = true
|
|
195
|
+
end
|
|
196
|
+
|
|
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
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
opts.on "-e", "--exclude PATTERN", "Exclude /regexp/ or string from run." do |a|
|
|
205
|
+
options[:exclude] = a
|
|
206
|
+
end
|
|
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
|
+
|
|
217
|
+
opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s|
|
|
218
|
+
options[:skip] = s.chars.to_a
|
|
219
|
+
end
|
|
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
|
+
|
|
233
|
+
unless extensions.empty?
|
|
234
|
+
opts.separator ""
|
|
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
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
begin
|
|
254
|
+
opts.parse! args
|
|
255
|
+
rescue OptionParser::InvalidOption => e
|
|
256
|
+
puts
|
|
257
|
+
puts e
|
|
258
|
+
puts
|
|
259
|
+
puts opts
|
|
260
|
+
exit 1
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
orig_args -= args
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
unless options[:seed] then
|
|
267
|
+
srand
|
|
268
|
+
options[:seed] = (ENV["SEED"] || srand).to_i % 0xFFFF
|
|
269
|
+
orig_args << "--seed" << options[:seed].to_s
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
options[:args] = orig_args.map { |s|
|
|
273
|
+
s.match?(/[\s|&<>$()]/) ? s.inspect : s
|
|
274
|
+
}.join " "
|
|
275
|
+
|
|
276
|
+
options
|
|
277
|
+
end
|
|
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
|
+
|
|
365
|
+
def self.filter_backtrace bt # :nodoc:
|
|
366
|
+
result = backtrace_filter.filter bt
|
|
367
|
+
result = bt.dup if result.empty?
|
|
368
|
+
result
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
##
|
|
372
|
+
# Represents anything "runnable", like Test, Spec, Benchmark, or
|
|
373
|
+
# whatever you can dream up.
|
|
374
|
+
#
|
|
375
|
+
# Subclasses of this are automatically registered and available in
|
|
376
|
+
# Runnable.runnables.
|
|
377
|
+
|
|
378
|
+
class Runnable
|
|
379
|
+
##
|
|
380
|
+
# Number of assertions executed in this run.
|
|
381
|
+
|
|
382
|
+
attr_accessor :assertions
|
|
383
|
+
|
|
384
|
+
##
|
|
385
|
+
# An assertion raised during the run, if any.
|
|
386
|
+
|
|
387
|
+
attr_accessor :failures
|
|
388
|
+
|
|
389
|
+
##
|
|
390
|
+
# The time it took to run.
|
|
391
|
+
|
|
392
|
+
attr_accessor :time
|
|
393
|
+
|
|
394
|
+
def time_it # :nodoc:
|
|
395
|
+
t0 = Minitest.clock_time
|
|
396
|
+
|
|
397
|
+
yield
|
|
398
|
+
ensure
|
|
399
|
+
self.time = Minitest.clock_time - t0
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
##
|
|
403
|
+
# Name of the run.
|
|
404
|
+
|
|
405
|
+
def name
|
|
406
|
+
@NAME
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
##
|
|
410
|
+
# Set the name of the run.
|
|
411
|
+
|
|
412
|
+
def name= o
|
|
413
|
+
@NAME = o
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
##
|
|
417
|
+
# Returns all instance methods matching the pattern +re+.
|
|
418
|
+
|
|
419
|
+
def self.methods_matching re
|
|
420
|
+
public_instance_methods(true).grep(re).map(&:to_s)
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def self.reset # :nodoc:
|
|
424
|
+
@@runnables = []
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
reset
|
|
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
|
+
|
|
447
|
+
##
|
|
448
|
+
# Responsible for running all runnable methods in a given class,
|
|
449
|
+
# each in its own instance. Each instance is passed to the
|
|
450
|
+
# reporter to record.
|
|
451
|
+
|
|
452
|
+
def Runnable.run_suite reporter, options = {}
|
|
453
|
+
filtered_methods = filter_runnable_methods options
|
|
454
|
+
|
|
455
|
+
return if filtered_methods.empty?
|
|
456
|
+
|
|
457
|
+
t0 = name = nil
|
|
458
|
+
|
|
459
|
+
@_info_handler = lambda do
|
|
460
|
+
unless reporter.passed? then
|
|
461
|
+
warn "Current results:"
|
|
462
|
+
warn reporter.reporters.grep(SummaryReporter).first
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
warn "Current: %s#%s %.2fs" % [self, name, Minitest.clock_time - t0]
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
with_info_handler do
|
|
469
|
+
filtered_methods.each do |method_name|
|
|
470
|
+
name = method_name
|
|
471
|
+
t0 = Minitest.clock_time
|
|
472
|
+
|
|
473
|
+
run self, method_name, reporter
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
##
|
|
479
|
+
# Runs a single method and has the reporter record the result.
|
|
480
|
+
# This was considered internal API but is factored out of run so
|
|
481
|
+
# that subclasses can specialize the running of an individual
|
|
482
|
+
# test. See Minitest::ParallelTest::ClassMethods for an example.
|
|
483
|
+
|
|
484
|
+
def Runnable.run klass, method_name, reporter
|
|
485
|
+
reporter.prerecord klass, method_name
|
|
486
|
+
reporter.record klass.new(method_name).run
|
|
487
|
+
end
|
|
488
|
+
|
|
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
|
|
496
|
+
|
|
497
|
+
def self.with_info_handler _reporter=nil, &block # :nodoc:
|
|
498
|
+
on_signal ::Minitest.info_signal, @_info_handler, &block
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
SIGNALS = Signal.list # :nodoc:
|
|
502
|
+
|
|
503
|
+
def self.on_signal name, action # :nodoc:
|
|
504
|
+
supported = SIGNALS[name]
|
|
505
|
+
|
|
506
|
+
old_trap = trap name do
|
|
507
|
+
old_trap.call if old_trap.respond_to? :call
|
|
508
|
+
action.call
|
|
509
|
+
end if supported
|
|
510
|
+
|
|
511
|
+
yield
|
|
512
|
+
ensure
|
|
513
|
+
trap name, old_trap if supported
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
##
|
|
517
|
+
# Each subclass of Runnable is responsible for overriding this
|
|
518
|
+
# method to return all runnable methods. See #methods_matching.
|
|
519
|
+
|
|
520
|
+
def self.runnable_methods
|
|
521
|
+
raise NotImplementedError, "subclass responsibility"
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
##
|
|
525
|
+
# Returns all subclasses of Runnable.
|
|
526
|
+
|
|
527
|
+
def self.runnables
|
|
528
|
+
@@runnables
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
def failure # :nodoc:
|
|
532
|
+
self.failures.first
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
def initialize name # :nodoc:
|
|
536
|
+
self.name = name
|
|
537
|
+
self.failures = []
|
|
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
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
##
|
|
567
|
+
# Runs a single method. Needs to return self.
|
|
568
|
+
|
|
569
|
+
def run
|
|
570
|
+
raise NotImplementedError, "subclass responsibility"
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
##
|
|
574
|
+
# Did this run pass?
|
|
575
|
+
#
|
|
576
|
+
# Note: skipped runs are not considered passing, but they don't
|
|
577
|
+
# cause the process to exit non-zero.
|
|
578
|
+
|
|
579
|
+
def passed?
|
|
580
|
+
raise NotImplementedError, "subclass responsibility"
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
##
|
|
584
|
+
# Returns a single character string to print based on the result
|
|
585
|
+
# of the run. One of <tt>"."</tt>, <tt>"F"</tt>,
|
|
586
|
+
# <tt>"E"</tt> or <tt>"S"</tt>.
|
|
587
|
+
|
|
588
|
+
def result_code
|
|
589
|
+
raise NotImplementedError, "subclass responsibility"
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
##
|
|
593
|
+
# Was this run skipped? See #passed? for more information.
|
|
594
|
+
|
|
595
|
+
def skipped?
|
|
596
|
+
raise NotImplementedError, "subclass responsibility"
|
|
597
|
+
end
|
|
598
|
+
end # Runnable
|
|
599
|
+
|
|
600
|
+
##
|
|
601
|
+
# Shared code for anything that can get passed to a Reporter. See
|
|
602
|
+
# Minitest::Test & Minitest::Result.
|
|
603
|
+
|
|
604
|
+
module Reportable
|
|
605
|
+
##
|
|
606
|
+
# Did this run pass?
|
|
607
|
+
#
|
|
608
|
+
# Note: skipped runs are not considered passing, but they don't
|
|
609
|
+
# cause the process to exit non-zero.
|
|
610
|
+
|
|
611
|
+
def passed?
|
|
612
|
+
not self.failure
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
BASE_DIR = "#{Dir.pwd}/" # :nodoc:
|
|
616
|
+
|
|
617
|
+
##
|
|
618
|
+
# The location identifier of this test. Depends on a method
|
|
619
|
+
# existing called class_name.
|
|
620
|
+
|
|
621
|
+
def location
|
|
622
|
+
loc = " [#{self.failure.location.delete_prefix BASE_DIR}]" unless passed? or error?
|
|
623
|
+
"#{self.class_name}##{self.name}#{loc}"
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
def class_name # :nodoc:
|
|
627
|
+
raise NotImplementedError, "subclass responsibility"
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
##
|
|
631
|
+
# Returns ".", "F", or "E" based on the result of the run.
|
|
632
|
+
|
|
633
|
+
def result_code
|
|
634
|
+
self.failure and self.failure.result_code or "."
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
##
|
|
638
|
+
# Was this run skipped?
|
|
639
|
+
|
|
640
|
+
def skipped?
|
|
641
|
+
self.failure and Skip === self.failure
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
##
|
|
645
|
+
# Did this run error?
|
|
646
|
+
|
|
647
|
+
def error?
|
|
648
|
+
self.failures.any? UnexpectedError
|
|
649
|
+
end
|
|
650
|
+
end # Reportable
|
|
651
|
+
|
|
652
|
+
##
|
|
653
|
+
# This represents a test result in a clean way that can be
|
|
654
|
+
# marshalled over a wire. Tests can do anything they want to the
|
|
655
|
+
# test instance and can create conditions that cause Marshal.dump to
|
|
656
|
+
# blow up. By using Result.from(a_test) you can be reasonably sure
|
|
657
|
+
# that the test result can be marshalled.
|
|
658
|
+
|
|
659
|
+
class Result < Runnable
|
|
660
|
+
include Minitest::Reportable
|
|
661
|
+
|
|
662
|
+
##
|
|
663
|
+
# The class name of the test result.
|
|
664
|
+
|
|
665
|
+
attr_accessor :klass
|
|
666
|
+
|
|
667
|
+
##
|
|
668
|
+
# The location of the test method.
|
|
669
|
+
|
|
670
|
+
attr_accessor :source_location
|
|
671
|
+
|
|
672
|
+
##
|
|
673
|
+
# Create a new test result from a Runnable instance.
|
|
674
|
+
|
|
675
|
+
def self.from runnable
|
|
676
|
+
o = runnable
|
|
677
|
+
|
|
678
|
+
r = self.new o.name
|
|
679
|
+
r.klass = o.class.name
|
|
680
|
+
r.assertions = o.assertions
|
|
681
|
+
r.failures = o.failures.dup
|
|
682
|
+
r.time = o.time
|
|
683
|
+
r.metadata = o.metadata if o.metadata?
|
|
684
|
+
|
|
685
|
+
r.source_location = o.method(o.name).source_location rescue ["unknown", -1]
|
|
686
|
+
|
|
687
|
+
r
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
def class_name # :nodoc:
|
|
691
|
+
self.klass # for Minitest::Reportable
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
def to_s # :nodoc:
|
|
695
|
+
return location if passed? and not skipped?
|
|
696
|
+
|
|
697
|
+
failures.map { |failure|
|
|
698
|
+
"#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n"
|
|
699
|
+
}.join "\n"
|
|
700
|
+
end
|
|
701
|
+
end # Result
|
|
702
|
+
|
|
703
|
+
##
|
|
704
|
+
# Defines the API for Reporters. Subclass this and override whatever
|
|
705
|
+
# you want. Go nuts.
|
|
706
|
+
|
|
707
|
+
class AbstractReporter
|
|
708
|
+
|
|
709
|
+
def initialize # :nodoc:
|
|
710
|
+
@mutex = Mutex.new
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
##
|
|
714
|
+
# Starts reporting on the run.
|
|
715
|
+
|
|
716
|
+
def start
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
##
|
|
720
|
+
# About to start running a test. This allows a reporter to show
|
|
721
|
+
# that it is starting or that we are in the middle of a test run.
|
|
722
|
+
|
|
723
|
+
def prerecord klass, name
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
##
|
|
727
|
+
# Output and record the result of the test. Call
|
|
728
|
+
# {result#result_code}[rdoc-ref:Runnable#result_code] to get the
|
|
729
|
+
# result character string. Stores the result of the run if the run
|
|
730
|
+
# did not pass.
|
|
731
|
+
|
|
732
|
+
def record result
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
##
|
|
736
|
+
# Outputs the summary of the run.
|
|
737
|
+
|
|
738
|
+
def report
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
##
|
|
742
|
+
# Did this run pass?
|
|
743
|
+
|
|
744
|
+
def passed?
|
|
745
|
+
true
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
def synchronize &block # :nodoc:
|
|
749
|
+
@mutex.synchronize(&block)
|
|
750
|
+
end
|
|
751
|
+
end # AbstractReportera
|
|
752
|
+
|
|
753
|
+
class Reporter < AbstractReporter # :nodoc:
|
|
754
|
+
##
|
|
755
|
+
# The IO used to report.
|
|
756
|
+
|
|
757
|
+
attr_accessor :io
|
|
758
|
+
|
|
759
|
+
##
|
|
760
|
+
# Command-line options for this run.
|
|
761
|
+
|
|
762
|
+
attr_accessor :options
|
|
763
|
+
|
|
764
|
+
def initialize io = $stdout, options = {} # :nodoc:
|
|
765
|
+
super()
|
|
766
|
+
self.io = io
|
|
767
|
+
self.options = options
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
##
|
|
772
|
+
# A very simple reporter that prints the "dots" during the run.
|
|
773
|
+
#
|
|
774
|
+
# This is added to the top-level CompositeReporter at the start of
|
|
775
|
+
# the run. If you want to change the output of minitest via a
|
|
776
|
+
# plugin, pull this out of the composite and replace it with your
|
|
777
|
+
# own.
|
|
778
|
+
|
|
779
|
+
class ProgressReporter < Reporter
|
|
780
|
+
def prerecord klass, name # :nodoc:
|
|
781
|
+
return unless options[:verbose]
|
|
782
|
+
|
|
783
|
+
io.print "%s#%s = " % [klass.name, name]
|
|
784
|
+
io.flush
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
def record result # :nodoc:
|
|
788
|
+
io.print "%.2f s = " % [result.time] if options[:verbose]
|
|
789
|
+
io.print result.result_code
|
|
790
|
+
io.puts if options[:verbose]
|
|
791
|
+
end
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
##
|
|
795
|
+
# A reporter that gathers statistics about a test run. Does not do
|
|
796
|
+
# any IO because meant to be used as a parent class for a reporter
|
|
797
|
+
# that does.
|
|
798
|
+
#
|
|
799
|
+
# If you want to create an entirely different type of output (eg,
|
|
800
|
+
# CI, HTML, etc), this is the place to start.
|
|
801
|
+
#
|
|
802
|
+
# Example:
|
|
803
|
+
#
|
|
804
|
+
# class JenkinsCIReporter < StatisticsReporter
|
|
805
|
+
# def report
|
|
806
|
+
# super # Needed to calculate some statistics
|
|
807
|
+
#
|
|
808
|
+
# print "<testsuite "
|
|
809
|
+
# print "tests='#{count}' "
|
|
810
|
+
# print "failures='#{failures}' "
|
|
811
|
+
# # Remaining XML...
|
|
812
|
+
# end
|
|
813
|
+
# end
|
|
814
|
+
|
|
815
|
+
class StatisticsReporter < Reporter
|
|
816
|
+
##
|
|
817
|
+
# Total number of assertions.
|
|
818
|
+
|
|
819
|
+
attr_accessor :assertions
|
|
820
|
+
|
|
821
|
+
##
|
|
822
|
+
# Total number of test cases.
|
|
823
|
+
|
|
824
|
+
attr_accessor :count
|
|
825
|
+
|
|
826
|
+
##
|
|
827
|
+
# An +Array+ of test cases that failed or were skipped.
|
|
828
|
+
|
|
829
|
+
attr_accessor :results
|
|
830
|
+
|
|
831
|
+
##
|
|
832
|
+
# Time the test run started. If available, the monotonic clock is
|
|
833
|
+
# used and this is a +Float+, otherwise it's an instance of
|
|
834
|
+
# +Time+.
|
|
835
|
+
|
|
836
|
+
attr_accessor :start_time
|
|
837
|
+
|
|
838
|
+
##
|
|
839
|
+
# Test run time. If available, the monotonic clock is used and
|
|
840
|
+
# this is a +Float+, otherwise it's an instance of +Time+.
|
|
841
|
+
|
|
842
|
+
attr_accessor :total_time
|
|
843
|
+
|
|
844
|
+
##
|
|
845
|
+
# Total number of tests that failed.
|
|
846
|
+
|
|
847
|
+
attr_accessor :failures
|
|
848
|
+
|
|
849
|
+
##
|
|
850
|
+
# Total number of tests that erred.
|
|
851
|
+
|
|
852
|
+
attr_accessor :errors
|
|
853
|
+
|
|
854
|
+
##
|
|
855
|
+
# Total number of tests that warned.
|
|
856
|
+
|
|
857
|
+
attr_accessor :warnings
|
|
858
|
+
|
|
859
|
+
##
|
|
860
|
+
# Total number of tests that where skipped.
|
|
861
|
+
|
|
862
|
+
attr_accessor :skips
|
|
863
|
+
|
|
864
|
+
def initialize io = $stdout, options = {} # :nodoc:
|
|
865
|
+
super
|
|
866
|
+
|
|
867
|
+
self.assertions = 0
|
|
868
|
+
self.count = 0
|
|
869
|
+
self.results = []
|
|
870
|
+
self.start_time = nil
|
|
871
|
+
self.total_time = nil
|
|
872
|
+
self.failures = nil
|
|
873
|
+
self.errors = nil
|
|
874
|
+
self.warnings = nil
|
|
875
|
+
self.skips = nil
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
def passed? # :nodoc:
|
|
879
|
+
results.all?(&:skipped?)
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
def start # :nodoc:
|
|
883
|
+
self.start_time = Minitest.clock_time
|
|
884
|
+
end
|
|
885
|
+
|
|
886
|
+
def record result # :nodoc:
|
|
887
|
+
self.count += 1
|
|
888
|
+
self.assertions += result.assertions
|
|
889
|
+
|
|
890
|
+
results << result if not result.passed? or result.skipped?
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
##
|
|
894
|
+
# Report on the tracked statistics.
|
|
895
|
+
|
|
896
|
+
def report
|
|
897
|
+
aggregate = results.group_by { |r| r.failure.class }
|
|
898
|
+
aggregate.default = [] # dumb. group_by should provide this
|
|
899
|
+
|
|
900
|
+
self.total_time = Minitest.clock_time - start_time
|
|
901
|
+
self.failures = aggregate[Assertion].size
|
|
902
|
+
self.errors = aggregate[UnexpectedError].size
|
|
903
|
+
self.warnings = aggregate[UnexpectedWarning].size
|
|
904
|
+
self.skips = aggregate[Skip].size
|
|
905
|
+
end
|
|
906
|
+
end # StatisticsReporter
|
|
907
|
+
|
|
908
|
+
##
|
|
909
|
+
# A reporter that prints the header, summary, and failure details at
|
|
910
|
+
# the end of the run.
|
|
911
|
+
#
|
|
912
|
+
# This is added to the top-level CompositeReporter at the start of
|
|
913
|
+
# the run. If you want to change the output of minitest via a
|
|
914
|
+
# plugin, pull this out of the composite and replace it with your
|
|
915
|
+
# own.
|
|
916
|
+
|
|
917
|
+
class SummaryReporter < StatisticsReporter
|
|
918
|
+
attr_accessor :sync # :nodoc:
|
|
919
|
+
attr_accessor :old_sync # :nodoc:
|
|
920
|
+
|
|
921
|
+
def start # :nodoc:
|
|
922
|
+
super
|
|
923
|
+
|
|
924
|
+
io.puts "Run options: #{options[:args]}"
|
|
925
|
+
io.puts
|
|
926
|
+
io.puts "# Running:"
|
|
927
|
+
io.puts
|
|
928
|
+
|
|
929
|
+
self.sync = io.respond_to? :"sync="
|
|
930
|
+
self.old_sync, io.sync = io.sync, true if self.sync
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
def report # :nodoc:
|
|
934
|
+
super
|
|
935
|
+
|
|
936
|
+
io.sync = self.old_sync
|
|
937
|
+
|
|
938
|
+
io.puts unless options[:verbose] # finish the dots
|
|
939
|
+
io.puts
|
|
940
|
+
io.puts statistics
|
|
941
|
+
aggregated_results io
|
|
942
|
+
io.puts summary
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
def statistics # :nodoc:
|
|
946
|
+
"Finished in %.6fs, %.4f runs/s, %.4f assertions/s." %
|
|
947
|
+
[total_time, count / total_time, assertions / total_time]
|
|
948
|
+
end
|
|
949
|
+
|
|
950
|
+
def aggregated_results io # :nodoc:
|
|
951
|
+
filtered_results = results.dup
|
|
952
|
+
filtered_results.reject!(&:skipped?) unless
|
|
953
|
+
options[:verbose] or options[:show_skips]
|
|
954
|
+
|
|
955
|
+
skip = options[:skip] || []
|
|
956
|
+
|
|
957
|
+
filtered_results.each_with_index { |result, i|
|
|
958
|
+
next if skip.include? result.result_code
|
|
959
|
+
|
|
960
|
+
io.puts "\n%3d) %s" % [i+1, result]
|
|
961
|
+
}
|
|
962
|
+
io.puts
|
|
963
|
+
io
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
def to_s # :nodoc:
|
|
967
|
+
aggregated_results(StringIO.new("".b)).string
|
|
968
|
+
end
|
|
969
|
+
|
|
970
|
+
def summary # :nodoc:
|
|
971
|
+
extra = []
|
|
972
|
+
|
|
973
|
+
extra << ", %d warnings" % [warnings] if options[:Werror]
|
|
974
|
+
|
|
975
|
+
extra << "\n\nYou have skipped tests. Run with --verbose for details." if
|
|
976
|
+
results.any?(&:skipped?) unless
|
|
977
|
+
options[:verbose] or
|
|
978
|
+
options[:show_skips] or
|
|
979
|
+
ENV["MT_NO_SKIP_MSG"]
|
|
980
|
+
|
|
981
|
+
"%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
|
|
982
|
+
[count, assertions, failures, errors, skips, extra.join]
|
|
983
|
+
end
|
|
984
|
+
end # SummaryReporter
|
|
985
|
+
|
|
986
|
+
##
|
|
987
|
+
# Dispatch to multiple reporters as one.
|
|
988
|
+
|
|
989
|
+
class CompositeReporter < AbstractReporter
|
|
990
|
+
##
|
|
991
|
+
# The list of reporters to dispatch to.
|
|
992
|
+
|
|
993
|
+
attr_accessor :reporters
|
|
994
|
+
|
|
995
|
+
def initialize *reporters # :nodoc:
|
|
996
|
+
super()
|
|
997
|
+
self.reporters = reporters
|
|
998
|
+
end
|
|
999
|
+
|
|
1000
|
+
def io # :nodoc:
|
|
1001
|
+
reporters.first.io
|
|
1002
|
+
end
|
|
1003
|
+
|
|
1004
|
+
##
|
|
1005
|
+
# Add another reporter to the mix.
|
|
1006
|
+
|
|
1007
|
+
def << reporter
|
|
1008
|
+
self.reporters << reporter
|
|
1009
|
+
end
|
|
1010
|
+
|
|
1011
|
+
def passed? # :nodoc:
|
|
1012
|
+
self.reporters.all?(&:passed?)
|
|
1013
|
+
end
|
|
1014
|
+
|
|
1015
|
+
def start # :nodoc:
|
|
1016
|
+
self.reporters.each(&:start)
|
|
1017
|
+
end
|
|
1018
|
+
|
|
1019
|
+
def prerecord klass, name # :nodoc:
|
|
1020
|
+
self.reporters.each do |reporter|
|
|
1021
|
+
reporter.prerecord klass, name
|
|
1022
|
+
end
|
|
1023
|
+
end
|
|
1024
|
+
|
|
1025
|
+
def record result # :nodoc:
|
|
1026
|
+
self.reporters.each do |reporter|
|
|
1027
|
+
reporter.record result
|
|
1028
|
+
end
|
|
1029
|
+
end
|
|
1030
|
+
|
|
1031
|
+
def report # :nodoc:
|
|
1032
|
+
self.reporters.each(&:report)
|
|
1033
|
+
end
|
|
1034
|
+
end # CompositeReporter
|
|
1035
|
+
|
|
1036
|
+
##
|
|
1037
|
+
# Represents run failures.
|
|
1038
|
+
|
|
1039
|
+
class Assertion < Exception
|
|
1040
|
+
RE = /in [`'](?:[^']+[#.])?(?:assert|refute|flunk|pass|fail|raise|must|wont)/ # :nodoc:
|
|
1041
|
+
|
|
1042
|
+
def error # :nodoc:
|
|
1043
|
+
self
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
##
|
|
1047
|
+
# Where was this run before an assertion was raised?
|
|
1048
|
+
|
|
1049
|
+
def location
|
|
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 .*$/, "")
|
|
1055
|
+
end
|
|
1056
|
+
|
|
1057
|
+
def result_code # :nodoc:
|
|
1058
|
+
result_label[0, 1]
|
|
1059
|
+
end
|
|
1060
|
+
|
|
1061
|
+
def result_label # :nodoc:
|
|
1062
|
+
"Failure"
|
|
1063
|
+
end
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
##
|
|
1067
|
+
# Assertion raised when skipping a run.
|
|
1068
|
+
|
|
1069
|
+
class Skip < Assertion
|
|
1070
|
+
def result_label # :nodoc:
|
|
1071
|
+
"Skipped"
|
|
1072
|
+
end
|
|
1073
|
+
end
|
|
1074
|
+
|
|
1075
|
+
##
|
|
1076
|
+
# Assertion wrapping an unexpected error that was raised during a run.
|
|
1077
|
+
|
|
1078
|
+
class UnexpectedError < Assertion
|
|
1079
|
+
include Minitest::Compress
|
|
1080
|
+
|
|
1081
|
+
# TODO: figure out how to use `cause` instead
|
|
1082
|
+
attr_accessor :error # :nodoc:
|
|
1083
|
+
|
|
1084
|
+
def initialize error # :nodoc:
|
|
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
|
+
|
|
1094
|
+
self.error = error
|
|
1095
|
+
end
|
|
1096
|
+
|
|
1097
|
+
def backtrace # :nodoc:
|
|
1098
|
+
self.error.backtrace
|
|
1099
|
+
end
|
|
1100
|
+
|
|
1101
|
+
BASE_RE = %r%#{Regexp.escape Dir.pwd}/% # :nodoc:
|
|
1102
|
+
|
|
1103
|
+
def message # :nodoc:
|
|
1104
|
+
bt = Minitest.filter_backtrace(self.backtrace).join("\n ")
|
|
1105
|
+
.gsub(BASE_RE, "")
|
|
1106
|
+
"#{self.error.class}: #{self.error.message}\n #{bt}"
|
|
1107
|
+
end
|
|
1108
|
+
|
|
1109
|
+
def result_label # :nodoc:
|
|
1110
|
+
"Error"
|
|
1111
|
+
end
|
|
1112
|
+
end
|
|
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
|
+
|
|
1123
|
+
##
|
|
1124
|
+
# Provides a simple set of guards that you can use in your tests
|
|
1125
|
+
# to skip execution if it is not applicable. These methods are
|
|
1126
|
+
# mixed into Test as both instance and class methods so you
|
|
1127
|
+
# can use them inside or outside of the test methods.
|
|
1128
|
+
#
|
|
1129
|
+
# def test_something_for_mri
|
|
1130
|
+
# skip "bug 1234" if jruby?
|
|
1131
|
+
# # ...
|
|
1132
|
+
# end
|
|
1133
|
+
#
|
|
1134
|
+
# if windows? then
|
|
1135
|
+
# # ... lots of test methods ...
|
|
1136
|
+
# end
|
|
1137
|
+
|
|
1138
|
+
module Guard
|
|
1139
|
+
|
|
1140
|
+
##
|
|
1141
|
+
# Is this running on jruby?
|
|
1142
|
+
|
|
1143
|
+
def jruby? platform = RUBY_PLATFORM
|
|
1144
|
+
"java" == platform
|
|
1145
|
+
end
|
|
1146
|
+
|
|
1147
|
+
##
|
|
1148
|
+
# Is this running on mri?
|
|
1149
|
+
|
|
1150
|
+
def mri? platform = RUBY_DESCRIPTION
|
|
1151
|
+
platform.start_with? "ruby"
|
|
1152
|
+
end
|
|
1153
|
+
|
|
1154
|
+
##
|
|
1155
|
+
# Is this running on macOS?
|
|
1156
|
+
|
|
1157
|
+
def osx? platform = RUBY_PLATFORM
|
|
1158
|
+
platform.include? "darwin"
|
|
1159
|
+
end
|
|
1160
|
+
|
|
1161
|
+
##
|
|
1162
|
+
# Is this running on windows?
|
|
1163
|
+
|
|
1164
|
+
def windows? platform = RUBY_PLATFORM
|
|
1165
|
+
/mswin|mingw/.match? platform
|
|
1166
|
+
end
|
|
1167
|
+
end
|
|
1168
|
+
|
|
1169
|
+
##
|
|
1170
|
+
# The standard backtrace filter for minitest.
|
|
1171
|
+
#
|
|
1172
|
+
# See Minitest.backtrace_filter=.
|
|
1173
|
+
|
|
1174
|
+
class BacktraceFilter
|
|
1175
|
+
|
|
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
|
|
1186
|
+
|
|
1187
|
+
##
|
|
1188
|
+
# Filter +bt+ to something useful. Returns the whole thing if
|
|
1189
|
+
# $DEBUG (ruby) or $MT_DEBUG (env).
|
|
1190
|
+
|
|
1191
|
+
def filter bt
|
|
1192
|
+
return ["No backtrace"] unless bt
|
|
1193
|
+
|
|
1194
|
+
return bt.dup if $DEBUG || ENV["MT_DEBUG"]
|
|
1195
|
+
|
|
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?
|
|
1199
|
+
|
|
1200
|
+
new_bt
|
|
1201
|
+
end
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1204
|
+
self.backtrace_filter = BacktraceFilter.new
|
|
1205
|
+
|
|
1206
|
+
# :stopdoc:
|
|
1207
|
+
|
|
1208
|
+
if defined? Process::CLOCK_MONOTONIC # :nodoc:
|
|
1209
|
+
def self.clock_time
|
|
1210
|
+
Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
1211
|
+
end
|
|
1212
|
+
else
|
|
1213
|
+
def self.clock_time
|
|
1214
|
+
Time.now
|
|
1215
|
+
end
|
|
1216
|
+
end
|
|
1217
|
+
|
|
1218
|
+
class Runnable # re-open
|
|
1219
|
+
def self.inherited klass # :nodoc:
|
|
1220
|
+
self.runnables << klass
|
|
1221
|
+
super
|
|
1222
|
+
end
|
|
1223
|
+
end
|
|
1224
|
+
|
|
1225
|
+
# :startdoc:
|
|
1226
|
+
end
|
|
1227
|
+
|
|
1228
|
+
require_relative "minitest/test"
|
|
1229
|
+
if ENV["MINITEST_SERVER"] then
|
|
1230
|
+
require_relative "minitest/server_plugin"
|
|
1231
|
+
Minitest.register_plugin :server
|
|
1232
|
+
end
|