minitest 5.11.3 → 5.27.0
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 +426 -4
- data/Manifest.txt +6 -0
- data/README.rdoc +119 -20
- data/Rakefile +28 -17
- data/design_rationale.rb +21 -19
- data/lib/hoe/minitest.rb +4 -6
- data/lib/minitest/assertions.rb +257 -100
- data/lib/minitest/autorun.rb +4 -11
- data/lib/minitest/benchmark.rb +15 -18
- data/lib/minitest/compress.rb +94 -0
- data/lib/minitest/error_on_warning.rb +11 -0
- data/lib/minitest/expectations.rb +72 -35
- data/lib/minitest/hell.rb +1 -1
- data/lib/minitest/manual_plugins.rb +16 -0
- data/lib/minitest/mock.rb +131 -44
- data/lib/minitest/parallel.rb +7 -5
- data/lib/minitest/pride.rb +1 -1
- data/lib/minitest/pride_plugin.rb +18 -25
- data/lib/minitest/spec.rb +47 -25
- data/lib/minitest/test.rb +54 -36
- data/lib/minitest/test_task.rb +324 -0
- data/lib/minitest/unit.rb +6 -9
- data/lib/minitest.rb +443 -180
- data/test/minitest/metametameta.rb +65 -17
- data/test/minitest/test_minitest_assertions.rb +1677 -0
- data/test/minitest/test_minitest_benchmark.rb +3 -3
- data/test/minitest/test_minitest_mock.rb +405 -66
- data/test/minitest/test_minitest_reporter.rb +174 -36
- data/test/minitest/test_minitest_spec.rb +368 -196
- data/test/minitest/test_minitest_test.rb +476 -1244
- data/test/minitest/test_minitest_test_task.rb +57 -0
- data.tar.gz.sig +0 -0
- metadata +50 -23
- metadata.gz.sig +0 -0
data/lib/minitest.rb
CHANGED
|
@@ -1,61 +1,83 @@
|
|
|
1
1
|
require "optparse"
|
|
2
|
-
require "thread"
|
|
3
|
-
require "mutex_m"
|
|
4
|
-
require "minitest/parallel"
|
|
5
2
|
require "stringio"
|
|
3
|
+
require "etc"
|
|
4
|
+
|
|
5
|
+
require_relative "minitest/parallel"
|
|
6
|
+
require_relative "minitest/compress"
|
|
6
7
|
|
|
7
8
|
##
|
|
8
|
-
#
|
|
9
|
+
# The top-level namespace for Minitest. Also the location of the main
|
|
10
|
+
# runtime. See +Minitest.run+ for more information.
|
|
9
11
|
|
|
10
12
|
module Minitest
|
|
11
|
-
VERSION = "5.
|
|
12
|
-
ENCS = "".respond_to? :encoding # :nodoc:
|
|
13
|
+
VERSION = "5.26.2" # :nodoc:
|
|
13
14
|
|
|
14
15
|
@@installed_at_exit ||= false
|
|
15
16
|
@@after_run = []
|
|
16
17
|
@extensions = []
|
|
17
18
|
|
|
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
|
|
19
30
|
|
|
20
31
|
##
|
|
21
32
|
# Parallel test executor
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
cattr_accessor :parallel_executor
|
|
35
|
+
|
|
36
|
+
warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"] && ENV["N"].to_i > 0
|
|
37
|
+
n_threads = (ENV["MT_CPU"] || ENV["N"] || Etc.nprocessors).to_i
|
|
38
|
+
|
|
39
|
+
self.parallel_executor = Parallel::Executor.new n_threads if n_threads > 1
|
|
25
40
|
|
|
26
41
|
##
|
|
27
42
|
# Filter object for backtraces.
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
cattr_accessor :backtrace_filter
|
|
30
45
|
|
|
31
46
|
##
|
|
32
47
|
# Reporter object to be used for all runs.
|
|
33
48
|
#
|
|
34
49
|
# NOTE: This accessor is only available during setup, not during runs.
|
|
35
50
|
|
|
36
|
-
|
|
51
|
+
cattr_accessor :reporter
|
|
37
52
|
|
|
38
53
|
##
|
|
39
54
|
# Names of known extension plugins.
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
cattr_accessor :extensions
|
|
42
57
|
|
|
43
58
|
##
|
|
44
59
|
# The signal to use for dumping information to STDERR. Defaults to "INFO".
|
|
45
60
|
|
|
46
|
-
|
|
61
|
+
cattr_accessor :info_signal
|
|
47
62
|
self.info_signal = "INFO"
|
|
48
63
|
|
|
64
|
+
cattr_accessor :allow_fork
|
|
65
|
+
self.allow_fork = false
|
|
66
|
+
|
|
49
67
|
##
|
|
50
68
|
# Registers Minitest to run at process exit
|
|
51
69
|
|
|
52
70
|
def self.autorun
|
|
71
|
+
Warning[:deprecated] = true
|
|
72
|
+
|
|
53
73
|
at_exit {
|
|
54
74
|
next if $! and not ($!.kind_of? SystemExit and $!.success?)
|
|
55
75
|
|
|
56
76
|
exit_code = nil
|
|
57
77
|
|
|
78
|
+
pid = Process.pid
|
|
58
79
|
at_exit {
|
|
80
|
+
next if !Minitest.allow_fork && Process.pid != pid
|
|
59
81
|
@@after_run.reverse_each(&:call)
|
|
60
82
|
exit exit_code || false
|
|
61
83
|
}
|
|
@@ -75,20 +97,19 @@ module Minitest
|
|
|
75
97
|
@@after_run << block
|
|
76
98
|
end
|
|
77
99
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
83
106
|
end
|
|
84
107
|
|
|
85
108
|
def self.load_plugins # :nodoc:
|
|
86
|
-
return unless
|
|
109
|
+
return unless defined? Gem
|
|
87
110
|
|
|
88
111
|
seen = {}
|
|
89
112
|
|
|
90
|
-
require "rubygems" unless defined? Gem
|
|
91
|
-
|
|
92
113
|
Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
|
|
93
114
|
name = File.basename plugin_path, "_plugin.rb"
|
|
94
115
|
|
|
@@ -100,93 +121,65 @@ module Minitest
|
|
|
100
121
|
end
|
|
101
122
|
end
|
|
102
123
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
# klass.new(runnable_method).run
|
|
119
|
-
|
|
120
|
-
def self.run args = []
|
|
121
|
-
self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
|
|
122
|
-
|
|
123
|
-
options = process_args args
|
|
124
|
-
|
|
125
|
-
reporter = CompositeReporter.new
|
|
126
|
-
reporter << SummaryReporter.new(options[:io], options)
|
|
127
|
-
reporter << ProgressReporter.new(options[:io], options)
|
|
128
|
-
|
|
129
|
-
self.reporter = reporter # this makes it available to plugins
|
|
130
|
-
self.init_plugins options
|
|
131
|
-
self.reporter = nil # runnables shouldn't depend on the reporter, ever
|
|
132
|
-
|
|
133
|
-
self.parallel_executor.start if parallel_executor.respond_to?(:start)
|
|
134
|
-
reporter.start
|
|
135
|
-
begin
|
|
136
|
-
__run reporter, options
|
|
137
|
-
rescue Interrupt
|
|
138
|
-
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
|
|
139
139
|
end
|
|
140
|
-
self.parallel_executor.shutdown
|
|
141
|
-
reporter.report
|
|
142
|
-
|
|
143
|
-
reporter.passed?
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
##
|
|
147
|
-
# Internal run method. Responsible for telling all Runnable
|
|
148
|
-
# sub-classes to run.
|
|
149
|
-
|
|
150
|
-
def self.__run reporter, options
|
|
151
|
-
suites = Runnable.runnables.reject { |s| s.runnable_methods.empty? }.shuffle
|
|
152
|
-
parallel, serial = suites.partition { |s| s.test_order == :parallel }
|
|
153
|
-
|
|
154
|
-
# If we run the parallel tests before the serial tests, the parallel tests
|
|
155
|
-
# could run in parallel with the serial tests. This would be bad because
|
|
156
|
-
# the serial tests won't lock around Reporter#record. Run the serial tests
|
|
157
|
-
# first, so that after they complete, the parallel tests will lock when
|
|
158
|
-
# recording results.
|
|
159
|
-
serial.map { |suite| suite.run reporter, options } +
|
|
160
|
-
parallel.map { |suite| suite.run reporter, options }
|
|
161
140
|
end
|
|
162
141
|
|
|
163
142
|
def self.process_args args = [] # :nodoc:
|
|
164
143
|
options = {
|
|
165
|
-
|
|
144
|
+
:io => $stdout,
|
|
166
145
|
}
|
|
167
146
|
orig_args = args.dup
|
|
168
147
|
|
|
169
148
|
OptionParser.new do |opts|
|
|
170
|
-
opts.
|
|
149
|
+
opts.program_name = "minitest"
|
|
171
150
|
opts.version = Minitest::VERSION
|
|
172
151
|
|
|
152
|
+
opts.banner = [
|
|
153
|
+
"Usage: rake test [A=options] (see Minitest::TestTask for more options)",
|
|
154
|
+
"minitest [paths] [options] (with minitest-sprint gem)",
|
|
155
|
+
"ruby path/to/test.rb [options]\n\n",
|
|
156
|
+
].join "\n or: "
|
|
157
|
+
|
|
173
158
|
opts.on "-h", "--help", "Display this help." do
|
|
174
159
|
puts opts
|
|
175
160
|
exit
|
|
176
161
|
end
|
|
177
162
|
|
|
178
|
-
opts.on "--no-plugins", "Bypass minitest plugin auto-loading (or
|
|
163
|
+
opts.on "--no-plugins", "Bypass minitest plugin auto-loading (or env: MT_NO_PLUGINS=1)."
|
|
179
164
|
|
|
180
|
-
desc = "Sets random seed. Also via env
|
|
165
|
+
desc = "Sets random seed. Also via env, eg: SEED=42"
|
|
181
166
|
opts.on "-s", "--seed SEED", Integer, desc do |m|
|
|
182
|
-
options[:seed] = m
|
|
167
|
+
options[:seed] = m
|
|
183
168
|
end
|
|
184
169
|
|
|
185
|
-
opts.on "-v", "--verbose", "Verbose.
|
|
170
|
+
opts.on "-v", "--verbose", "Verbose. Print each name as they run." do
|
|
186
171
|
options[:verbose] = true
|
|
187
172
|
end
|
|
188
173
|
|
|
189
|
-
opts.on "-
|
|
174
|
+
opts.on "-q", "--quiet", "Quiet. Show no dots while processing files." do
|
|
175
|
+
options[:quiet] = true
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
opts.on "--show-skips", "Show skipped at the end of run." do
|
|
179
|
+
options[:show_skips] = true
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
opts.on "-n", "--name PATTERN", "Include /regexp/ or string for run." do |a|
|
|
190
183
|
options[:filter] = a
|
|
191
184
|
end
|
|
192
185
|
|
|
@@ -194,13 +187,48 @@ module Minitest
|
|
|
194
187
|
options[:exclude] = a
|
|
195
188
|
end
|
|
196
189
|
|
|
190
|
+
# part of my unofficial embedded gem "makeoptparseworkwell"
|
|
191
|
+
def opts.topdict(name) = (name.length > 1 ? top.long : top.short)
|
|
192
|
+
def opts.alias(from, to) = (dict = topdict(from) ; dict[to] = dict[from])
|
|
193
|
+
|
|
194
|
+
# these will work but won't show up in --help output:
|
|
195
|
+
opts.alias "name", "include"
|
|
196
|
+
opts.alias "n", "i"
|
|
197
|
+
opts.alias "e", "x"
|
|
198
|
+
|
|
199
|
+
opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s|
|
|
200
|
+
options[:skip] = s.chars.to_a
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
opts.on "-W[error]", String, "Turn Ruby warnings into errors" do |s|
|
|
204
|
+
options[:Werror] = true
|
|
205
|
+
case s
|
|
206
|
+
when "error", "all", nil then
|
|
207
|
+
require_relative "minitest/error_on_warning"
|
|
208
|
+
$VERBOSE = true
|
|
209
|
+
::Warning[:deprecated] = true
|
|
210
|
+
else
|
|
211
|
+
::Warning[s.to_sym] = true # check validity of category
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
197
215
|
unless extensions.empty?
|
|
198
216
|
opts.separator ""
|
|
199
|
-
opts.separator "Known extensions: #{extensions.join
|
|
200
|
-
|
|
201
|
-
extensions.each do |
|
|
202
|
-
|
|
203
|
-
|
|
217
|
+
opts.separator "Known extensions: #{extensions.join ", "}"
|
|
218
|
+
|
|
219
|
+
extensions.each do |mod_or_meth|
|
|
220
|
+
case mod_or_meth
|
|
221
|
+
when Symbol, String then
|
|
222
|
+
meth = mod_or_meth
|
|
223
|
+
msg = "plugin_#{meth}_options"
|
|
224
|
+
send msg, opts, options if respond_to? msg
|
|
225
|
+
when Module
|
|
226
|
+
recv = mod_or_meth
|
|
227
|
+
next unless recv.respond_to? :minitest_plugin_options
|
|
228
|
+
recv.minitest_plugin_options opts, options
|
|
229
|
+
else
|
|
230
|
+
raise ArgumentError, "plugin is %p, but it must be a symbol, string or module" % [mod_or_meth]
|
|
231
|
+
end
|
|
204
232
|
end
|
|
205
233
|
end
|
|
206
234
|
|
|
@@ -223,17 +251,106 @@ module Minitest
|
|
|
223
251
|
orig_args << "--seed" << options[:seed].to_s
|
|
224
252
|
end
|
|
225
253
|
|
|
226
|
-
srand options[:seed]
|
|
227
|
-
|
|
228
254
|
options[:args] = orig_args.map { |s|
|
|
229
|
-
s
|
|
255
|
+
s.match?(/[\s|&<>$()]/) ? s.inspect : s
|
|
230
256
|
}.join " "
|
|
231
257
|
|
|
232
258
|
options
|
|
233
259
|
end
|
|
234
260
|
|
|
261
|
+
##
|
|
262
|
+
# This is the top-level run method. Everything starts from here. It
|
|
263
|
+
# tells each Runnable sub-class to run, and each of those are
|
|
264
|
+
# responsible for doing whatever they do.
|
|
265
|
+
#
|
|
266
|
+
# The overall structure of a run looks like this:
|
|
267
|
+
#
|
|
268
|
+
# Minitest.autorun
|
|
269
|
+
# Minitest.run(args)
|
|
270
|
+
# Minitest.load_plugins
|
|
271
|
+
# Minitest.process_args
|
|
272
|
+
# Minitest.init_plugins
|
|
273
|
+
# Minitest.__run(reporter, options)
|
|
274
|
+
# Runnable.runnables.each |runnable_klass|
|
|
275
|
+
# runnable_klass.run(reporter, options)
|
|
276
|
+
# filtered_methods = runnable_methods.select {...}.reject {...}
|
|
277
|
+
# filtered_methods.each |runnable_method|
|
|
278
|
+
# runnable_klass.run_one_method(self, runnable_method, reporter)
|
|
279
|
+
# Minitest.run_one_method(runnable_klass, runnable_method)
|
|
280
|
+
# runnable_klass.new(runnable_method).run
|
|
281
|
+
|
|
282
|
+
def self.run args = []
|
|
283
|
+
self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
|
|
284
|
+
|
|
285
|
+
options = process_args args
|
|
286
|
+
|
|
287
|
+
Minitest.seed = options[:seed]
|
|
288
|
+
srand Minitest.seed
|
|
289
|
+
|
|
290
|
+
reporter = CompositeReporter.new
|
|
291
|
+
reporter << SummaryReporter.new(options[:io], options)
|
|
292
|
+
reporter << ProgressReporter.new(options[:io], options) unless options[:quiet]
|
|
293
|
+
|
|
294
|
+
self.reporter = reporter # this makes it available to plugins
|
|
295
|
+
self.init_plugins options
|
|
296
|
+
self.reporter = nil # runnables shouldn't depend on the reporter, ever
|
|
297
|
+
|
|
298
|
+
self.parallel_executor.start if parallel_executor.respond_to? :start
|
|
299
|
+
reporter.start
|
|
300
|
+
begin
|
|
301
|
+
__run reporter, options
|
|
302
|
+
finished = true
|
|
303
|
+
rescue Interrupt
|
|
304
|
+
warn "Interrupted. Exiting..."
|
|
305
|
+
end
|
|
306
|
+
self.parallel_executor.shutdown if parallel_executor.respond_to? :shutdown
|
|
307
|
+
|
|
308
|
+
# might have been removed/replaced during init_plugins:
|
|
309
|
+
summary = reporter.reporters.grep(SummaryReporter).first
|
|
310
|
+
|
|
311
|
+
reporter.report
|
|
312
|
+
|
|
313
|
+
return empty_run! options if finished && summary && summary.count == 0
|
|
314
|
+
finished and reporter.passed?
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def self.empty_run! options # :nodoc:
|
|
318
|
+
filter = options[:filter]
|
|
319
|
+
return true unless filter # no filter, but nothing ran == success
|
|
320
|
+
|
|
321
|
+
warn "Nothing ran for filter: %s" % [filter]
|
|
322
|
+
|
|
323
|
+
require "did_you_mean" # soft dependency, punt if it doesn't load
|
|
324
|
+
|
|
325
|
+
ms = Runnable.runnables.flat_map(&:runnable_methods)
|
|
326
|
+
cs = DidYouMean::SpellChecker.new(dictionary: ms).correct filter
|
|
327
|
+
|
|
328
|
+
warn DidYouMean::Formatter.message_for cs unless cs.empty?
|
|
329
|
+
rescue LoadError
|
|
330
|
+
# do nothing
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
##
|
|
334
|
+
# Internal run method. Responsible for telling all Runnable
|
|
335
|
+
# sub-classes to run.
|
|
336
|
+
|
|
337
|
+
def self.__run reporter, options
|
|
338
|
+
suites = Runnable.runnables.shuffle
|
|
339
|
+
parallel, serial = suites.partition { |s| s.test_order == :parallel }
|
|
340
|
+
|
|
341
|
+
# If we run the parallel tests before the serial tests, the parallel tests
|
|
342
|
+
# could run in parallel with the serial tests. This would be bad because
|
|
343
|
+
# the serial tests won't lock around Reporter#record. Run the serial tests
|
|
344
|
+
# first, so that after they complete, the parallel tests will lock when
|
|
345
|
+
# recording results.
|
|
346
|
+
serial.map { |suite| suite.run reporter, options } +
|
|
347
|
+
parallel.map { |suite| suite.run reporter, options }
|
|
348
|
+
end
|
|
349
|
+
|
|
235
350
|
def self.filter_backtrace bt # :nodoc:
|
|
236
|
-
backtrace_filter.filter bt
|
|
351
|
+
result = backtrace_filter.filter bt
|
|
352
|
+
result = bt.dup if result.empty?
|
|
353
|
+
result
|
|
237
354
|
end
|
|
238
355
|
|
|
239
356
|
##
|
|
@@ -300,24 +417,35 @@ module Minitest
|
|
|
300
417
|
# reporter to record.
|
|
301
418
|
|
|
302
419
|
def self.run reporter, options = {}
|
|
303
|
-
|
|
304
|
-
|
|
420
|
+
pos = options[:filter]
|
|
421
|
+
neg = options[:exclude]
|
|
305
422
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
exclude = options[:exclude]
|
|
311
|
-
exclude = Regexp.new $1 if exclude =~ %r%/(.*)/%
|
|
423
|
+
pos = Regexp.new $1 if pos.kind_of?(String) && pos =~ %r%/(.*)/%
|
|
424
|
+
neg = Regexp.new $1 if neg.kind_of?(String) && neg =~ %r%/(.*)/%
|
|
312
425
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
426
|
+
# at most 1-2% slower than a 1-pass version, stop optimizing this
|
|
427
|
+
filtered_methods = self.runnable_methods
|
|
428
|
+
.select { |m| !pos || pos === m || pos === "#{self}##{m}" }
|
|
429
|
+
.reject { |m| neg && (neg === m || neg === "#{self}##{m}") }
|
|
316
430
|
|
|
317
431
|
return if filtered_methods.empty?
|
|
318
432
|
|
|
433
|
+
t0 = name = nil
|
|
434
|
+
|
|
435
|
+
@_info_handler = lambda do
|
|
436
|
+
unless reporter.passed? then
|
|
437
|
+
warn "Current results:"
|
|
438
|
+
warn reporter.reporters.grep(SummaryReporter).first
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
warn "Current: %s#%s %.2fs" % [self, name, Minitest.clock_time - t0]
|
|
442
|
+
end
|
|
443
|
+
|
|
319
444
|
with_info_handler reporter do
|
|
320
445
|
filtered_methods.each do |method_name|
|
|
446
|
+
name = method_name
|
|
447
|
+
t0 = Minitest.clock_time
|
|
448
|
+
|
|
321
449
|
run_one_method self, method_name, reporter
|
|
322
450
|
end
|
|
323
451
|
end
|
|
@@ -334,17 +462,16 @@ module Minitest
|
|
|
334
462
|
reporter.record Minitest.run_one_method(klass, method_name)
|
|
335
463
|
end
|
|
336
464
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
end
|
|
345
|
-
end
|
|
465
|
+
##
|
|
466
|
+
# Defines the order to run tests (:random by default). Override
|
|
467
|
+
# this or use a convenience method to change it for your tests.
|
|
468
|
+
|
|
469
|
+
def self.test_order
|
|
470
|
+
:random
|
|
471
|
+
end
|
|
346
472
|
|
|
347
|
-
|
|
473
|
+
def self.with_info_handler reporter, &block # :nodoc:
|
|
474
|
+
on_signal ::Minitest.info_signal, @_info_handler, &block
|
|
348
475
|
end
|
|
349
476
|
|
|
350
477
|
SIGNALS = Signal.list # :nodoc:
|
|
@@ -382,7 +509,7 @@ module Minitest
|
|
|
382
509
|
def marshal_dump # :nodoc:
|
|
383
510
|
unless @@marshal_dump_warned then
|
|
384
511
|
warn ["Minitest::Runnable#marshal_dump is deprecated.",
|
|
385
|
-
"You might be violating internals. From", caller.first].join " "
|
|
512
|
+
"You might be violating internals. From", caller(1..1).first].join " "
|
|
386
513
|
@@marshal_dump_warned = true
|
|
387
514
|
end
|
|
388
515
|
|
|
@@ -401,6 +528,31 @@ module Minitest
|
|
|
401
528
|
self.name = name
|
|
402
529
|
self.failures = []
|
|
403
530
|
self.assertions = 0
|
|
531
|
+
# lazy initializer for metadata
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
##
|
|
535
|
+
# Metadata you attach to the test results that get sent to the reporter.
|
|
536
|
+
#
|
|
537
|
+
# Lazily initializes to a hash, to keep memory down.
|
|
538
|
+
#
|
|
539
|
+
# NOTE: this data *must* be plain (read: marshal-able) data!
|
|
540
|
+
# Hashes! Arrays! Strings!
|
|
541
|
+
|
|
542
|
+
def metadata
|
|
543
|
+
@metadata ||= {}
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
##
|
|
547
|
+
# Sets metadata, mainly used for +Result.from+.
|
|
548
|
+
|
|
549
|
+
attr_writer :metadata
|
|
550
|
+
|
|
551
|
+
##
|
|
552
|
+
# Returns true if metadata exists.
|
|
553
|
+
|
|
554
|
+
def metadata?
|
|
555
|
+
defined? @metadata
|
|
404
556
|
end
|
|
405
557
|
|
|
406
558
|
##
|
|
@@ -422,7 +574,8 @@ module Minitest
|
|
|
422
574
|
|
|
423
575
|
##
|
|
424
576
|
# Returns a single character string to print based on the result
|
|
425
|
-
# of the run.
|
|
577
|
+
# of the run. One of <tt>"."</tt>, <tt>"F"</tt>,
|
|
578
|
+
# <tt>"E"</tt> or <tt>"S"</tt>.
|
|
426
579
|
|
|
427
580
|
def result_code
|
|
428
581
|
raise NotImplementedError, "subclass responsibility"
|
|
@@ -434,7 +587,7 @@ module Minitest
|
|
|
434
587
|
def skipped?
|
|
435
588
|
raise NotImplementedError, "subclass responsibility"
|
|
436
589
|
end
|
|
437
|
-
end
|
|
590
|
+
end # Runnable
|
|
438
591
|
|
|
439
592
|
##
|
|
440
593
|
# Shared code for anything that can get passed to a Reporter. See
|
|
@@ -451,12 +604,14 @@ module Minitest
|
|
|
451
604
|
not self.failure
|
|
452
605
|
end
|
|
453
606
|
|
|
607
|
+
BASE_DIR = "#{Dir.pwd}/" # :nodoc:
|
|
608
|
+
|
|
454
609
|
##
|
|
455
610
|
# The location identifier of this test. Depends on a method
|
|
456
611
|
# existing called class_name.
|
|
457
612
|
|
|
458
613
|
def location
|
|
459
|
-
loc = " [#{self.failure.location}]" unless passed? or error?
|
|
614
|
+
loc = " [#{self.failure.location.delete_prefix BASE_DIR}]" unless passed? or error?
|
|
460
615
|
"#{self.class_name}##{self.name}#{loc}"
|
|
461
616
|
end
|
|
462
617
|
|
|
@@ -482,9 +637,9 @@ module Minitest
|
|
|
482
637
|
# Did this run error?
|
|
483
638
|
|
|
484
639
|
def error?
|
|
485
|
-
self.failures.any?
|
|
640
|
+
self.failures.any? UnexpectedError
|
|
486
641
|
end
|
|
487
|
-
end
|
|
642
|
+
end # Reportable
|
|
488
643
|
|
|
489
644
|
##
|
|
490
645
|
# This represents a test result in a clean way that can be
|
|
@@ -520,6 +675,7 @@ module Minitest
|
|
|
520
675
|
r.assertions = o.assertions
|
|
521
676
|
r.failures = o.failures.dup
|
|
522
677
|
r.time = o.time
|
|
678
|
+
r.metadata = o.metadata if o.metadata?
|
|
523
679
|
|
|
524
680
|
r.source_location = o.method(o.name).source_location rescue ["unknown", -1]
|
|
525
681
|
|
|
@@ -537,14 +693,17 @@ module Minitest
|
|
|
537
693
|
"#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n"
|
|
538
694
|
}.join "\n"
|
|
539
695
|
end
|
|
540
|
-
end
|
|
696
|
+
end # Result
|
|
541
697
|
|
|
542
698
|
##
|
|
543
699
|
# Defines the API for Reporters. Subclass this and override whatever
|
|
544
700
|
# you want. Go nuts.
|
|
545
701
|
|
|
546
702
|
class AbstractReporter
|
|
547
|
-
|
|
703
|
+
|
|
704
|
+
def initialize # :nodoc:
|
|
705
|
+
@mutex = Mutex.new
|
|
706
|
+
end
|
|
548
707
|
|
|
549
708
|
##
|
|
550
709
|
# Starts reporting on the run.
|
|
@@ -560,8 +719,10 @@ module Minitest
|
|
|
560
719
|
end
|
|
561
720
|
|
|
562
721
|
##
|
|
563
|
-
#
|
|
564
|
-
# result
|
|
722
|
+
# Output and record the result of the test. Call
|
|
723
|
+
# {result#result_code}[rdoc-ref:Runnable#result_code] to get the
|
|
724
|
+
# result character string. Stores the result of the run if the run
|
|
725
|
+
# did not pass.
|
|
565
726
|
|
|
566
727
|
def record result
|
|
567
728
|
end
|
|
@@ -578,7 +739,11 @@ module Minitest
|
|
|
578
739
|
def passed?
|
|
579
740
|
true
|
|
580
741
|
end
|
|
581
|
-
|
|
742
|
+
|
|
743
|
+
def synchronize &block # :nodoc:
|
|
744
|
+
@mutex.synchronize(&block)
|
|
745
|
+
end
|
|
746
|
+
end # AbstractReportera
|
|
582
747
|
|
|
583
748
|
class Reporter < AbstractReporter # :nodoc:
|
|
584
749
|
##
|
|
@@ -607,11 +772,11 @@ module Minitest
|
|
|
607
772
|
# own.
|
|
608
773
|
|
|
609
774
|
class ProgressReporter < Reporter
|
|
610
|
-
def prerecord klass, name
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
775
|
+
def prerecord klass, name # :nodoc:
|
|
776
|
+
return unless options[:verbose]
|
|
777
|
+
|
|
778
|
+
io.print "%s#%s = " % [klass.name, name]
|
|
779
|
+
io.flush
|
|
615
780
|
end
|
|
616
781
|
|
|
617
782
|
def record result # :nodoc:
|
|
@@ -628,18 +793,68 @@ module Minitest
|
|
|
628
793
|
#
|
|
629
794
|
# If you want to create an entirely different type of output (eg,
|
|
630
795
|
# CI, HTML, etc), this is the place to start.
|
|
796
|
+
#
|
|
797
|
+
# Example:
|
|
798
|
+
#
|
|
799
|
+
# class JenkinsCIReporter < StatisticsReporter
|
|
800
|
+
# def report
|
|
801
|
+
# super # Needed to calculate some statistics
|
|
802
|
+
#
|
|
803
|
+
# print "<testsuite "
|
|
804
|
+
# print "tests='#{count}' "
|
|
805
|
+
# print "failures='#{failures}' "
|
|
806
|
+
# # Remaining XML...
|
|
807
|
+
# end
|
|
808
|
+
# end
|
|
631
809
|
|
|
632
810
|
class StatisticsReporter < Reporter
|
|
633
|
-
|
|
811
|
+
##
|
|
812
|
+
# Total number of assertions.
|
|
813
|
+
|
|
634
814
|
attr_accessor :assertions
|
|
815
|
+
|
|
816
|
+
##
|
|
817
|
+
# Total number of test cases.
|
|
818
|
+
|
|
635
819
|
attr_accessor :count
|
|
820
|
+
|
|
821
|
+
##
|
|
822
|
+
# An +Array+ of test cases that failed or were skipped.
|
|
823
|
+
|
|
636
824
|
attr_accessor :results
|
|
825
|
+
|
|
826
|
+
##
|
|
827
|
+
# Time the test run started. If available, the monotonic clock is
|
|
828
|
+
# used and this is a +Float+, otherwise it's an instance of
|
|
829
|
+
# +Time+.
|
|
830
|
+
|
|
637
831
|
attr_accessor :start_time
|
|
832
|
+
|
|
833
|
+
##
|
|
834
|
+
# Test run time. If available, the monotonic clock is used and
|
|
835
|
+
# this is a +Float+, otherwise it's an instance of +Time+.
|
|
836
|
+
|
|
638
837
|
attr_accessor :total_time
|
|
838
|
+
|
|
839
|
+
##
|
|
840
|
+
# Total number of tests that failed.
|
|
841
|
+
|
|
639
842
|
attr_accessor :failures
|
|
843
|
+
|
|
844
|
+
##
|
|
845
|
+
# Total number of tests that erred.
|
|
846
|
+
|
|
640
847
|
attr_accessor :errors
|
|
848
|
+
|
|
849
|
+
##
|
|
850
|
+
# Total number of tests that warned.
|
|
851
|
+
|
|
852
|
+
attr_accessor :warnings
|
|
853
|
+
|
|
854
|
+
##
|
|
855
|
+
# Total number of tests that where skipped.
|
|
856
|
+
|
|
641
857
|
attr_accessor :skips
|
|
642
|
-
# :startdoc:
|
|
643
858
|
|
|
644
859
|
def initialize io = $stdout, options = {} # :nodoc:
|
|
645
860
|
super
|
|
@@ -651,6 +866,7 @@ module Minitest
|
|
|
651
866
|
self.total_time = nil
|
|
652
867
|
self.failures = nil
|
|
653
868
|
self.errors = nil
|
|
869
|
+
self.warnings = nil
|
|
654
870
|
self.skips = nil
|
|
655
871
|
end
|
|
656
872
|
|
|
@@ -669,16 +885,20 @@ module Minitest
|
|
|
669
885
|
results << result if not result.passed? or result.skipped?
|
|
670
886
|
end
|
|
671
887
|
|
|
672
|
-
|
|
888
|
+
##
|
|
889
|
+
# Report on the tracked statistics.
|
|
890
|
+
|
|
891
|
+
def report
|
|
673
892
|
aggregate = results.group_by { |r| r.failure.class }
|
|
674
893
|
aggregate.default = [] # dumb. group_by should provide this
|
|
675
894
|
|
|
676
895
|
self.total_time = Minitest.clock_time - start_time
|
|
677
896
|
self.failures = aggregate[Assertion].size
|
|
678
897
|
self.errors = aggregate[UnexpectedError].size
|
|
898
|
+
self.warnings = aggregate[UnexpectedWarning].size
|
|
679
899
|
self.skips = aggregate[Skip].size
|
|
680
900
|
end
|
|
681
|
-
end
|
|
901
|
+
end # StatisticsReporter
|
|
682
902
|
|
|
683
903
|
##
|
|
684
904
|
# A reporter that prints the header, summary, and failure details at
|
|
@@ -690,10 +910,8 @@ module Minitest
|
|
|
690
910
|
# own.
|
|
691
911
|
|
|
692
912
|
class SummaryReporter < StatisticsReporter
|
|
693
|
-
# :
|
|
694
|
-
attr_accessor :
|
|
695
|
-
attr_accessor :old_sync
|
|
696
|
-
# :startdoc:
|
|
913
|
+
attr_accessor :sync # :nodoc:
|
|
914
|
+
attr_accessor :old_sync # :nodoc:
|
|
697
915
|
|
|
698
916
|
def start # :nodoc:
|
|
699
917
|
super
|
|
@@ -703,7 +921,7 @@ module Minitest
|
|
|
703
921
|
io.puts "# Running:"
|
|
704
922
|
io.puts
|
|
705
923
|
|
|
706
|
-
self.sync = io.respond_to? :"sync="
|
|
924
|
+
self.sync = io.respond_to? :"sync="
|
|
707
925
|
self.old_sync, io.sync = io.sync, true if self.sync
|
|
708
926
|
end
|
|
709
927
|
|
|
@@ -726,9 +944,14 @@ module Minitest
|
|
|
726
944
|
|
|
727
945
|
def aggregated_results io # :nodoc:
|
|
728
946
|
filtered_results = results.dup
|
|
729
|
-
filtered_results.reject!(&:skipped?) unless
|
|
947
|
+
filtered_results.reject!(&:skipped?) unless
|
|
948
|
+
options[:verbose] or options[:show_skips]
|
|
949
|
+
|
|
950
|
+
skip = options[:skip] || []
|
|
730
951
|
|
|
731
952
|
filtered_results.each_with_index { |result, i|
|
|
953
|
+
next if skip.include? result.result_code
|
|
954
|
+
|
|
732
955
|
io.puts "\n%3d) %s" % [i+1, result]
|
|
733
956
|
}
|
|
734
957
|
io.puts
|
|
@@ -736,27 +959,24 @@ module Minitest
|
|
|
736
959
|
end
|
|
737
960
|
|
|
738
961
|
def to_s # :nodoc:
|
|
739
|
-
aggregated_results(StringIO.new(
|
|
962
|
+
aggregated_results(StringIO.new("".b)).string
|
|
740
963
|
end
|
|
741
964
|
|
|
742
965
|
def summary # :nodoc:
|
|
743
|
-
extra =
|
|
744
|
-
|
|
745
|
-
extra = "\n\nYou have skipped tests. Run with --verbose for details." if
|
|
746
|
-
results.any?(&:skipped?) unless options[:verbose] or ENV["MT_NO_SKIP_MSG"]
|
|
966
|
+
extra = []
|
|
747
967
|
|
|
748
|
-
|
|
749
|
-
[count, assertions, failures, errors, skips, extra]
|
|
750
|
-
end
|
|
968
|
+
extra << ", %d warnings" % [warnings] if options[:Werror]
|
|
751
969
|
|
|
752
|
-
|
|
970
|
+
extra << "\n\nYou have skipped tests. Run with --verbose for details." if
|
|
971
|
+
results.any?(&:skipped?) unless
|
|
972
|
+
options[:verbose] or
|
|
973
|
+
options[:show_skips] or
|
|
974
|
+
ENV["MT_NO_SKIP_MSG"]
|
|
753
975
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
else
|
|
757
|
-
def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end
|
|
976
|
+
"%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
|
|
977
|
+
[count, assertions, failures, errors, skips, extra.join]
|
|
758
978
|
end
|
|
759
|
-
end
|
|
979
|
+
end # SummaryReporter
|
|
760
980
|
|
|
761
981
|
##
|
|
762
982
|
# Dispatch to multiple reporters as one.
|
|
@@ -807,12 +1027,14 @@ module Minitest
|
|
|
807
1027
|
def report # :nodoc:
|
|
808
1028
|
self.reporters.each(&:report)
|
|
809
1029
|
end
|
|
810
|
-
end
|
|
1030
|
+
end # CompositeReporter
|
|
811
1031
|
|
|
812
1032
|
##
|
|
813
1033
|
# Represents run failures.
|
|
814
1034
|
|
|
815
1035
|
class Assertion < Exception
|
|
1036
|
+
RE = /in [`'](?:[^']+[#.])?(?:assert|refute|flunk|pass|fail|raise|must|wont)/ # :nodoc:
|
|
1037
|
+
|
|
816
1038
|
def error # :nodoc:
|
|
817
1039
|
self
|
|
818
1040
|
end
|
|
@@ -821,12 +1043,11 @@ module Minitest
|
|
|
821
1043
|
# Where was this run before an assertion was raised?
|
|
822
1044
|
|
|
823
1045
|
def location
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
last_before_assertion.sub(/:in .*$/, "")
|
|
1046
|
+
bt = Minitest.filter_backtrace self.backtrace
|
|
1047
|
+
idx = bt.rindex { |s| s.match? RE } || -1 # fall back to first item
|
|
1048
|
+
loc = bt[idx+1] || bt.last || "unknown:-1"
|
|
1049
|
+
|
|
1050
|
+
loc.sub(/:in .*$/, "")
|
|
830
1051
|
end
|
|
831
1052
|
|
|
832
1053
|
def result_code # :nodoc:
|
|
@@ -851,24 +1072,34 @@ module Minitest
|
|
|
851
1072
|
# Assertion wrapping an unexpected error that was raised during a run.
|
|
852
1073
|
|
|
853
1074
|
class UnexpectedError < Assertion
|
|
854
|
-
|
|
1075
|
+
include Minitest::Compress
|
|
855
1076
|
|
|
856
|
-
|
|
1077
|
+
# TODO: figure out how to use `cause` instead
|
|
1078
|
+
attr_accessor :error # :nodoc:
|
|
1079
|
+
|
|
1080
|
+
def initialize error # :nodoc:
|
|
857
1081
|
super "Unexpected exception"
|
|
858
|
-
|
|
1082
|
+
|
|
1083
|
+
if SystemStackError === error then
|
|
1084
|
+
bt = error.backtrace
|
|
1085
|
+
new_bt = compress bt
|
|
1086
|
+
error = error.exception "#{bt.size} -> #{new_bt.size}"
|
|
1087
|
+
error.set_backtrace new_bt
|
|
1088
|
+
end
|
|
1089
|
+
|
|
1090
|
+
self.error = error
|
|
859
1091
|
end
|
|
860
1092
|
|
|
861
1093
|
def backtrace # :nodoc:
|
|
862
|
-
self.
|
|
1094
|
+
self.error.backtrace
|
|
863
1095
|
end
|
|
864
1096
|
|
|
865
|
-
|
|
866
|
-
self.exception
|
|
867
|
-
end
|
|
1097
|
+
BASE_RE = %r%#{Regexp.escape Dir.pwd}/% # :nodoc:
|
|
868
1098
|
|
|
869
1099
|
def message # :nodoc:
|
|
870
|
-
bt = Minitest.filter_backtrace(self.backtrace).join
|
|
871
|
-
|
|
1100
|
+
bt = Minitest.filter_backtrace(self.backtrace).join("\n ")
|
|
1101
|
+
.gsub(BASE_RE, "")
|
|
1102
|
+
"#{self.error.class}: #{self.error.message}\n #{bt}"
|
|
872
1103
|
end
|
|
873
1104
|
|
|
874
1105
|
def result_label # :nodoc:
|
|
@@ -876,6 +1107,15 @@ module Minitest
|
|
|
876
1107
|
end
|
|
877
1108
|
end
|
|
878
1109
|
|
|
1110
|
+
##
|
|
1111
|
+
# Assertion raised on warning when running in -Werror mode.
|
|
1112
|
+
|
|
1113
|
+
class UnexpectedWarning < Assertion
|
|
1114
|
+
def result_label # :nodoc:
|
|
1115
|
+
"Warning"
|
|
1116
|
+
end
|
|
1117
|
+
end
|
|
1118
|
+
|
|
879
1119
|
##
|
|
880
1120
|
# Provides a simple set of guards that you can use in your tests
|
|
881
1121
|
# to skip execution if it is not applicable. These methods are
|
|
@@ -904,6 +1144,9 @@ module Minitest
|
|
|
904
1144
|
# Is this running on maglev?
|
|
905
1145
|
|
|
906
1146
|
def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
|
1147
|
+
where = Minitest.filter_backtrace(caller).first
|
|
1148
|
+
where = where.split(":in ", 2).first # clean up noise
|
|
1149
|
+
warn "DEPRECATED: `maglev?` called from #{where}. This will fail in Minitest 6."
|
|
907
1150
|
"maglev" == platform
|
|
908
1151
|
end
|
|
909
1152
|
|
|
@@ -911,13 +1154,23 @@ module Minitest
|
|
|
911
1154
|
# Is this running on mri?
|
|
912
1155
|
|
|
913
1156
|
def mri? platform = RUBY_DESCRIPTION
|
|
914
|
-
|
|
1157
|
+
platform.start_with? "ruby"
|
|
1158
|
+
end
|
|
1159
|
+
|
|
1160
|
+
##
|
|
1161
|
+
# Is this running on macOS?
|
|
1162
|
+
|
|
1163
|
+
def osx? platform = RUBY_PLATFORM
|
|
1164
|
+
platform.include? "darwin"
|
|
915
1165
|
end
|
|
916
1166
|
|
|
917
1167
|
##
|
|
918
1168
|
# Is this running on rubinius?
|
|
919
1169
|
|
|
920
1170
|
def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
|
1171
|
+
where = Minitest.filter_backtrace(caller).first
|
|
1172
|
+
where = where.split(":in ", 2).first # clean up noise
|
|
1173
|
+
warn "DEPRECATED: `rubinius?` called from #{where}. This will fail in Minitest 6."
|
|
921
1174
|
"rbx" == platform
|
|
922
1175
|
end
|
|
923
1176
|
|
|
@@ -925,7 +1178,7 @@ module Minitest
|
|
|
925
1178
|
# Is this running on windows?
|
|
926
1179
|
|
|
927
1180
|
def windows? platform = RUBY_PLATFORM
|
|
928
|
-
/mswin|mingw
|
|
1181
|
+
/mswin|mingw/.match? platform
|
|
929
1182
|
end
|
|
930
1183
|
end
|
|
931
1184
|
|
|
@@ -936,19 +1189,29 @@ module Minitest
|
|
|
936
1189
|
|
|
937
1190
|
class BacktraceFilter
|
|
938
1191
|
|
|
939
|
-
MT_RE = %r%lib/minitest%
|
|
1192
|
+
MT_RE = %r%lib/minitest|internal:warning% # :nodoc:
|
|
1193
|
+
|
|
1194
|
+
##
|
|
1195
|
+
# The regular expression to use to filter backtraces. Defaults to +MT_RE+.
|
|
1196
|
+
|
|
1197
|
+
attr_accessor :regexp
|
|
1198
|
+
|
|
1199
|
+
def initialize regexp = MT_RE # :nodoc:
|
|
1200
|
+
self.regexp = regexp
|
|
1201
|
+
end
|
|
940
1202
|
|
|
941
1203
|
##
|
|
942
|
-
# Filter +bt+ to something useful. Returns the whole thing if
|
|
1204
|
+
# Filter +bt+ to something useful. Returns the whole thing if
|
|
1205
|
+
# $DEBUG (ruby) or $MT_DEBUG (env).
|
|
943
1206
|
|
|
944
1207
|
def filter bt
|
|
945
1208
|
return ["No backtrace"] unless bt
|
|
946
1209
|
|
|
947
|
-
return bt.dup if $DEBUG
|
|
1210
|
+
return bt.dup if $DEBUG || ENV["MT_DEBUG"]
|
|
948
1211
|
|
|
949
|
-
new_bt = bt.take_while { |line| line
|
|
950
|
-
new_bt = bt.select { |line| line
|
|
951
|
-
new_bt = bt.dup
|
|
1212
|
+
new_bt = bt.take_while { |line| !regexp.match? line.to_s }
|
|
1213
|
+
new_bt = bt.select { |line| !regexp.match? line.to_s } if new_bt.empty?
|
|
1214
|
+
new_bt = bt.dup if new_bt.empty?
|
|
952
1215
|
|
|
953
1216
|
new_bt
|
|
954
1217
|
end
|
|
@@ -984,4 +1247,4 @@ module Minitest
|
|
|
984
1247
|
# :startdoc:
|
|
985
1248
|
end
|
|
986
1249
|
|
|
987
|
-
|
|
1250
|
+
require_relative "minitest/test"
|