minitest 5.12.2

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.
@@ -0,0 +1,72 @@
1
+ # -*- ruby -*-
2
+
3
+ require "rubygems"
4
+ require "hoe"
5
+
6
+ Hoe.plugin :seattlerb
7
+ Hoe.plugin :rdoc
8
+
9
+ Hoe.spec "minitest" do
10
+ developer "Ryan Davis", "ryand-ruby@zenspider.com"
11
+
12
+ license "MIT"
13
+
14
+ require_ruby_version "~> 2.2"
15
+ end
16
+
17
+ desc "Find missing expectations"
18
+ task :specs do
19
+ $:.unshift "lib"
20
+ require "minitest/test"
21
+ require "minitest/spec"
22
+
23
+ pos_prefix, neg_prefix = "must", "wont"
24
+ skip_re = /^(must|wont)$|wont_(throw)|must_(block|not?_|nothing|raise$)/x
25
+ dont_flip_re = /(must|wont)_(include|respond_to)/
26
+
27
+ map = {
28
+ /(must_throw)s/ => '\1',
29
+ /(?!not)_same/ => "_be_same_as",
30
+ /_in_/ => "_be_within_",
31
+ /_operator/ => "_be",
32
+ /_includes/ => "_include",
33
+ /(must|wont)_(.*_of|nil|silent|empty)/ => '\1_be_\2',
34
+ /must_raises/ => "must_raise",
35
+ }
36
+
37
+ expectations = Minitest::Expectations.public_instance_methods.map(&:to_s)
38
+ assertions = Minitest::Assertions.public_instance_methods.map(&:to_s)
39
+
40
+ assertions.sort.each do |assertion|
41
+ expectation = case assertion
42
+ when /^assert/ then
43
+ assertion.sub(/^assert/, pos_prefix.to_s)
44
+ when /^refute/ then
45
+ assertion.sub(/^refute/, neg_prefix.to_s)
46
+ end
47
+
48
+ next unless expectation
49
+ next if expectation =~ skip_re
50
+
51
+ regexp, replacement = map.find { |re, _| expectation =~ re }
52
+ expectation.sub! regexp, replacement if replacement
53
+
54
+ next if expectations.include? expectation
55
+
56
+ args = [assertion, expectation].map(&:to_sym).map(&:inspect)
57
+ args << :reverse if expectation =~ dont_flip_re
58
+
59
+ puts
60
+ puts "##"
61
+ puts "# :method: #{expectation}"
62
+ puts "# See Minitest::Assertions##{assertion}"
63
+ puts
64
+ puts "infect_an_assertion #{args.join ", "}"
65
+ end
66
+ end
67
+
68
+ task :bugs do
69
+ sh "for f in bug*.rb ; do echo $f; echo; #{Gem.ruby} -Ilib $f && rm $f ; done"
70
+ end
71
+
72
+ # vim: syntax=Ruby
@@ -0,0 +1,52 @@
1
+ # Specs: # Equivalent Unit Tests:
2
+ ###############################################################################
3
+ describe Thingy do # class TestThingy < Minitest::Test
4
+ before do # def setup
5
+ do_some_setup # super
6
+ end # do_some_setup
7
+ # end
8
+ it "should do the first thing" do #
9
+ 1.must_equal 1 # def test_first_thing
10
+ end # assert_equal 1, 1
11
+ # end
12
+ describe SubThingy do # end
13
+ before do #
14
+ do_more_setup # class TestSubThingy < TestThingy
15
+ end # def setup
16
+ # super
17
+ it "should do the second thing" do # do_more_setup
18
+ 2.must_equal 2 # end
19
+ end #
20
+ end # def test_second_thing
21
+ end # assert_equal 2, 2
22
+ # end
23
+ # end
24
+ ###############################################################################
25
+ # runs 2 specs # runs 3 tests
26
+ ###############################################################################
27
+ # The specs generate:
28
+
29
+ class ThingySpec < Minitest::Spec
30
+ def setup
31
+ super
32
+ do_some_setup
33
+ end
34
+
35
+ def test_should_do_the_first_thing
36
+ assert_equal 1, 1
37
+ end
38
+ end
39
+
40
+ class SubThingySpec < ThingySpec
41
+ def setup
42
+ super
43
+ do_more_setup
44
+ end
45
+
46
+ # because only setup/teardown is inherited, not specs
47
+ remove_method :test_should_do_the_first_thing
48
+
49
+ def test_should_do_the_second_thing
50
+ assert_equal 2, 2
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+ # :stopdoc:
2
+
3
+ class Hoe
4
+ end
5
+
6
+ module Hoe::Minitest
7
+ def minitest?
8
+ self.name == "minitest"
9
+ end
10
+
11
+ def initialize_minitest
12
+ unless minitest? then
13
+ dir = "../../minitest/dev/lib"
14
+ Hoe.add_include_dirs dir if File.directory? dir
15
+ end
16
+
17
+ gem "minitest"
18
+ require "minitest"
19
+ version = Minitest::VERSION.split(/\./).first(2).join(".")
20
+
21
+ dependency "minitest", "~> #{version}", :development unless
22
+ minitest? or ENV["MT_NO_ISOLATE"]
23
+ end
24
+
25
+ def define_minitest_tasks
26
+ self.testlib = :minitest
27
+
28
+ # make sure we use the gemmed minitest on 1.9
29
+ self.test_prelude = 'gem "minitest"' unless
30
+ minitest? or ENV["MT_NO_ISOLATE"]
31
+ end
32
+ end
@@ -0,0 +1,1041 @@
1
+ require "optparse"
2
+ require "thread"
3
+ require "mutex_m"
4
+ require "minitest/parallel"
5
+ require "stringio"
6
+
7
+ ##
8
+ # :include: README.rdoc
9
+
10
+ module Minitest
11
+ VERSION = "5.12.2" # :nodoc:
12
+ ENCS = "".respond_to? :encoding # :nodoc:
13
+
14
+ @@installed_at_exit ||= false
15
+ @@after_run = []
16
+ @extensions = []
17
+
18
+ mc = (class << self; self; end)
19
+
20
+ ##
21
+ # Parallel test executor
22
+
23
+ mc.send :attr_accessor, :parallel_executor
24
+
25
+ warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"]
26
+ n_threads = (ENV["MT_CPU"] || ENV["N"] || 2).to_i
27
+ self.parallel_executor = Parallel::Executor.new n_threads
28
+
29
+ ##
30
+ # Filter object for backtraces.
31
+
32
+ mc.send :attr_accessor, :backtrace_filter
33
+
34
+ ##
35
+ # Reporter object to be used for all runs.
36
+ #
37
+ # NOTE: This accessor is only available during setup, not during runs.
38
+
39
+ mc.send :attr_accessor, :reporter
40
+
41
+ ##
42
+ # Names of known extension plugins.
43
+
44
+ mc.send :attr_accessor, :extensions
45
+
46
+ ##
47
+ # The signal to use for dumping information to STDERR. Defaults to "INFO".
48
+
49
+ mc.send :attr_accessor, :info_signal
50
+ self.info_signal = "INFO"
51
+
52
+ ##
53
+ # Registers Minitest to run at process exit
54
+
55
+ def self.autorun
56
+ at_exit {
57
+ next if $! and not ($!.kind_of? SystemExit and $!.success?)
58
+
59
+ exit_code = nil
60
+
61
+ at_exit {
62
+ @@after_run.reverse_each(&:call)
63
+ exit exit_code || false
64
+ }
65
+
66
+ exit_code = Minitest.run ARGV
67
+ } unless @@installed_at_exit
68
+ @@installed_at_exit = true
69
+ end
70
+
71
+ ##
72
+ # A simple hook allowing you to run a block of code after everything
73
+ # is done running. Eg:
74
+ #
75
+ # Minitest.after_run { p $debugging_info }
76
+
77
+ def self.after_run &block
78
+ @@after_run << block
79
+ end
80
+
81
+ def self.init_plugins options # :nodoc:
82
+ self.extensions.each do |name|
83
+ msg = "plugin_#{name}_init"
84
+ send msg, options if self.respond_to? msg
85
+ end
86
+ end
87
+
88
+ def self.load_plugins # :nodoc:
89
+ return unless self.extensions.empty?
90
+
91
+ seen = {}
92
+
93
+ require "rubygems" unless defined? Gem
94
+
95
+ Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
96
+ name = File.basename plugin_path, "_plugin.rb"
97
+
98
+ next if seen[name]
99
+ seen[name] = true
100
+
101
+ require plugin_path
102
+ self.extensions << name
103
+ end
104
+ end
105
+
106
+ ##
107
+ # This is the top-level run method. Everything starts from here. It
108
+ # tells each Runnable sub-class to run, and each of those are
109
+ # responsible for doing whatever they do.
110
+ #
111
+ # The overall structure of a run looks like this:
112
+ #
113
+ # Minitest.autorun
114
+ # Minitest.run(args)
115
+ # Minitest.__run(reporter, options)
116
+ # Runnable.runnables.each
117
+ # runnable.run(reporter, options)
118
+ # self.runnable_methods.each
119
+ # self.run_one_method(self, runnable_method, reporter)
120
+ # Minitest.run_one_method(klass, runnable_method)
121
+ # klass.new(runnable_method).run
122
+
123
+ def self.run args = []
124
+ self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
125
+
126
+ options = process_args args
127
+
128
+ reporter = CompositeReporter.new
129
+ reporter << SummaryReporter.new(options[:io], options)
130
+ reporter << ProgressReporter.new(options[:io], options)
131
+
132
+ self.reporter = reporter # this makes it available to plugins
133
+ self.init_plugins options
134
+ self.reporter = nil # runnables shouldn't depend on the reporter, ever
135
+
136
+ self.parallel_executor.start if parallel_executor.respond_to?(:start)
137
+ reporter.start
138
+ begin
139
+ __run reporter, options
140
+ rescue Interrupt
141
+ warn "Interrupted. Exiting..."
142
+ end
143
+ self.parallel_executor.shutdown
144
+ reporter.report
145
+
146
+ reporter.passed?
147
+ end
148
+
149
+ ##
150
+ # Internal run method. Responsible for telling all Runnable
151
+ # sub-classes to run.
152
+
153
+ def self.__run reporter, options
154
+ suites = Runnable.runnables.reject { |s| s.runnable_methods.empty? }.shuffle
155
+ parallel, serial = suites.partition { |s| s.test_order == :parallel }
156
+
157
+ # If we run the parallel tests before the serial tests, the parallel tests
158
+ # could run in parallel with the serial tests. This would be bad because
159
+ # the serial tests won't lock around Reporter#record. Run the serial tests
160
+ # first, so that after they complete, the parallel tests will lock when
161
+ # recording results.
162
+ serial.map { |suite| suite.run reporter, options } +
163
+ parallel.map { |suite| suite.run reporter, options }
164
+ end
165
+
166
+ def self.process_args args = [] # :nodoc:
167
+ options = {
168
+ :io => $stdout,
169
+ }
170
+ orig_args = args.dup
171
+
172
+ OptionParser.new do |opts|
173
+ opts.banner = "minitest options:"
174
+ opts.version = Minitest::VERSION
175
+
176
+ opts.on "-h", "--help", "Display this help." do
177
+ puts opts
178
+ exit
179
+ end
180
+
181
+ opts.on "--no-plugins", "Bypass minitest plugin auto-loading (or set $MT_NO_PLUGINS)."
182
+
183
+ desc = "Sets random seed. Also via env. Eg: SEED=n rake"
184
+ opts.on "-s", "--seed SEED", Integer, desc do |m|
185
+ options[:seed] = m.to_i
186
+ end
187
+
188
+ opts.on "-v", "--verbose", "Verbose. Show progress processing files." do
189
+ options[:verbose] = true
190
+ end
191
+
192
+ opts.on "-n", "--name PATTERN", "Filter run on /regexp/ or string." do |a|
193
+ options[:filter] = a
194
+ end
195
+
196
+ opts.on "-e", "--exclude PATTERN", "Exclude /regexp/ or string from run." do |a|
197
+ options[:exclude] = a
198
+ end
199
+
200
+ unless extensions.empty?
201
+ opts.separator ""
202
+ opts.separator "Known extensions: #{extensions.join(", ")}"
203
+
204
+ extensions.each do |meth|
205
+ msg = "plugin_#{meth}_options"
206
+ send msg, opts, options if self.respond_to?(msg)
207
+ end
208
+ end
209
+
210
+ begin
211
+ opts.parse! args
212
+ rescue OptionParser::InvalidOption => e
213
+ puts
214
+ puts e
215
+ puts
216
+ puts opts
217
+ exit 1
218
+ end
219
+
220
+ orig_args -= args
221
+ end
222
+
223
+ unless options[:seed] then
224
+ srand
225
+ options[:seed] = (ENV["SEED"] || srand).to_i % 0xFFFF
226
+ orig_args << "--seed" << options[:seed].to_s
227
+ end
228
+
229
+ srand options[:seed]
230
+
231
+ options[:args] = orig_args.map { |s|
232
+ s =~ /[\s|&<>$()]/ ? s.inspect : s
233
+ }.join " "
234
+
235
+ options
236
+ end
237
+
238
+ def self.filter_backtrace bt # :nodoc:
239
+ backtrace_filter.filter bt
240
+ end
241
+
242
+ ##
243
+ # Represents anything "runnable", like Test, Spec, Benchmark, or
244
+ # whatever you can dream up.
245
+ #
246
+ # Subclasses of this are automatically registered and available in
247
+ # Runnable.runnables.
248
+
249
+ class Runnable
250
+ ##
251
+ # Number of assertions executed in this run.
252
+
253
+ attr_accessor :assertions
254
+
255
+ ##
256
+ # An assertion raised during the run, if any.
257
+
258
+ attr_accessor :failures
259
+
260
+ ##
261
+ # The time it took to run.
262
+
263
+ attr_accessor :time
264
+
265
+ def time_it # :nodoc:
266
+ t0 = Minitest.clock_time
267
+
268
+ yield
269
+ ensure
270
+ self.time = Minitest.clock_time - t0
271
+ end
272
+
273
+ ##
274
+ # Name of the run.
275
+
276
+ def name
277
+ @NAME
278
+ end
279
+
280
+ ##
281
+ # Set the name of the run.
282
+
283
+ def name= o
284
+ @NAME = o
285
+ end
286
+
287
+ ##
288
+ # Returns all instance methods matching the pattern +re+.
289
+
290
+ def self.methods_matching re
291
+ public_instance_methods(true).grep(re).map(&:to_s)
292
+ end
293
+
294
+ def self.reset # :nodoc:
295
+ @@runnables = []
296
+ end
297
+
298
+ reset
299
+
300
+ ##
301
+ # Responsible for running all runnable methods in a given class,
302
+ # each in its own instance. Each instance is passed to the
303
+ # reporter to record.
304
+
305
+ def self.run reporter, options = {}
306
+ filter = options[:filter] || "/./"
307
+ filter = Regexp.new $1 if filter.is_a?(String) && filter =~ %r%/(.*)/%
308
+
309
+ filtered_methods = self.runnable_methods.find_all { |m|
310
+ filter === m || filter === "#{self}##{m}"
311
+ }
312
+
313
+ exclude = options[:exclude]
314
+ exclude = Regexp.new $1 if exclude =~ %r%/(.*)/%
315
+
316
+ filtered_methods.delete_if { |m|
317
+ exclude === m || exclude === "#{self}##{m}"
318
+ }
319
+
320
+ return if filtered_methods.empty?
321
+
322
+ with_info_handler reporter do
323
+ filtered_methods.each do |method_name|
324
+ run_one_method self, method_name, reporter
325
+ end
326
+ end
327
+ end
328
+
329
+ ##
330
+ # Runs a single method and has the reporter record the result.
331
+ # This was considered internal API but is factored out of run so
332
+ # that subclasses can specialize the running of an individual
333
+ # test. See Minitest::ParallelTest::ClassMethods for an example.
334
+
335
+ def self.run_one_method klass, method_name, reporter
336
+ reporter.prerecord klass, method_name
337
+ reporter.record Minitest.run_one_method(klass, method_name)
338
+ end
339
+
340
+ def self.with_info_handler reporter, &block # :nodoc:
341
+ handler = lambda do
342
+ unless reporter.passed? then
343
+ warn "Current results:"
344
+ warn ""
345
+ warn reporter.reporters.first
346
+ warn ""
347
+ end
348
+ end
349
+
350
+ on_signal ::Minitest.info_signal, handler, &block
351
+ end
352
+
353
+ SIGNALS = Signal.list # :nodoc:
354
+
355
+ def self.on_signal name, action # :nodoc:
356
+ supported = SIGNALS[name]
357
+
358
+ old_trap = trap name do
359
+ old_trap.call if old_trap.respond_to? :call
360
+ action.call
361
+ end if supported
362
+
363
+ yield
364
+ ensure
365
+ trap name, old_trap if supported
366
+ end
367
+
368
+ ##
369
+ # Each subclass of Runnable is responsible for overriding this
370
+ # method to return all runnable methods. See #methods_matching.
371
+
372
+ def self.runnable_methods
373
+ raise NotImplementedError, "subclass responsibility"
374
+ end
375
+
376
+ ##
377
+ # Returns all subclasses of Runnable.
378
+
379
+ def self.runnables
380
+ @@runnables
381
+ end
382
+
383
+ @@marshal_dump_warned = false
384
+
385
+ def marshal_dump # :nodoc:
386
+ unless @@marshal_dump_warned then
387
+ warn ["Minitest::Runnable#marshal_dump is deprecated.",
388
+ "You might be violating internals. From", caller.first].join " "
389
+ @@marshal_dump_warned = true
390
+ end
391
+
392
+ [self.name, self.failures, self.assertions, self.time]
393
+ end
394
+
395
+ def marshal_load ary # :nodoc:
396
+ self.name, self.failures, self.assertions, self.time = ary
397
+ end
398
+
399
+ def failure # :nodoc:
400
+ self.failures.first
401
+ end
402
+
403
+ def initialize name # :nodoc:
404
+ self.name = name
405
+ self.failures = []
406
+ self.assertions = 0
407
+ end
408
+
409
+ ##
410
+ # Runs a single method. Needs to return self.
411
+
412
+ def run
413
+ raise NotImplementedError, "subclass responsibility"
414
+ end
415
+
416
+ ##
417
+ # Did this run pass?
418
+ #
419
+ # Note: skipped runs are not considered passing, but they don't
420
+ # cause the process to exit non-zero.
421
+
422
+ def passed?
423
+ raise NotImplementedError, "subclass responsibility"
424
+ end
425
+
426
+ ##
427
+ # Returns a single character string to print based on the result
428
+ # of the run. One of <tt>"."</tt>, <tt>"F"</tt>,
429
+ # <tt>"E"</tt> or <tt>"S"</tt>.
430
+
431
+ def result_code
432
+ raise NotImplementedError, "subclass responsibility"
433
+ end
434
+
435
+ ##
436
+ # Was this run skipped? See #passed? for more information.
437
+
438
+ def skipped?
439
+ raise NotImplementedError, "subclass responsibility"
440
+ end
441
+ end
442
+
443
+ ##
444
+ # Shared code for anything that can get passed to a Reporter. See
445
+ # Minitest::Test & Minitest::Result.
446
+
447
+ module Reportable
448
+ ##
449
+ # Did this run pass?
450
+ #
451
+ # Note: skipped runs are not considered passing, but they don't
452
+ # cause the process to exit non-zero.
453
+
454
+ def passed?
455
+ not self.failure
456
+ end
457
+
458
+ ##
459
+ # The location identifier of this test. Depends on a method
460
+ # existing called class_name.
461
+
462
+ def location
463
+ loc = " [#{self.failure.location}]" unless passed? or error?
464
+ "#{self.class_name}##{self.name}#{loc}"
465
+ end
466
+
467
+ def class_name # :nodoc:
468
+ raise NotImplementedError, "subclass responsibility"
469
+ end
470
+
471
+ ##
472
+ # Returns ".", "F", or "E" based on the result of the run.
473
+
474
+ def result_code
475
+ self.failure and self.failure.result_code or "."
476
+ end
477
+
478
+ ##
479
+ # Was this run skipped?
480
+
481
+ def skipped?
482
+ self.failure and Skip === self.failure
483
+ end
484
+
485
+ ##
486
+ # Did this run error?
487
+
488
+ def error?
489
+ self.failures.any? { |f| UnexpectedError === f }
490
+ end
491
+ end
492
+
493
+ ##
494
+ # This represents a test result in a clean way that can be
495
+ # marshalled over a wire. Tests can do anything they want to the
496
+ # test instance and can create conditions that cause Marshal.dump to
497
+ # blow up. By using Result.from(a_test) you can be reasonably sure
498
+ # that the test result can be marshalled.
499
+
500
+ class Result < Runnable
501
+ include Minitest::Reportable
502
+
503
+ undef_method :marshal_dump
504
+ undef_method :marshal_load
505
+
506
+ ##
507
+ # The class name of the test result.
508
+
509
+ attr_accessor :klass
510
+
511
+ ##
512
+ # The location of the test method.
513
+
514
+ attr_accessor :source_location
515
+
516
+ ##
517
+ # Create a new test result from a Runnable instance.
518
+
519
+ def self.from runnable
520
+ o = runnable
521
+
522
+ r = self.new o.name
523
+ r.klass = o.class.name
524
+ r.assertions = o.assertions
525
+ r.failures = o.failures.dup
526
+ r.time = o.time
527
+
528
+ r.source_location = o.method(o.name).source_location rescue ["unknown", -1]
529
+
530
+ r
531
+ end
532
+
533
+ def class_name # :nodoc:
534
+ self.klass # for Minitest::Reportable
535
+ end
536
+
537
+ def to_s # :nodoc:
538
+ return location if passed? and not skipped?
539
+
540
+ failures.map { |failure|
541
+ "#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n"
542
+ }.join "\n"
543
+ end
544
+ end
545
+
546
+ ##
547
+ # Defines the API for Reporters. Subclass this and override whatever
548
+ # you want. Go nuts.
549
+
550
+ class AbstractReporter
551
+ include Mutex_m
552
+
553
+ ##
554
+ # Starts reporting on the run.
555
+
556
+ def start
557
+ end
558
+
559
+ ##
560
+ # About to start running a test. This allows a reporter to show
561
+ # that it is starting or that we are in the middle of a test run.
562
+
563
+ def prerecord klass, name
564
+ end
565
+
566
+ ##
567
+ # Output and record the result of the test. Call
568
+ # {result#result_code}[rdoc-ref:Runnable#result_code] to get the
569
+ # result character string. Stores the result of the run if the run
570
+ # did not pass.
571
+
572
+ def record result
573
+ end
574
+
575
+ ##
576
+ # Outputs the summary of the run.
577
+
578
+ def report
579
+ end
580
+
581
+ ##
582
+ # Did this run pass?
583
+
584
+ def passed?
585
+ true
586
+ end
587
+ end
588
+
589
+ class Reporter < AbstractReporter # :nodoc:
590
+ ##
591
+ # The IO used to report.
592
+
593
+ attr_accessor :io
594
+
595
+ ##
596
+ # Command-line options for this run.
597
+
598
+ attr_accessor :options
599
+
600
+ def initialize io = $stdout, options = {} # :nodoc:
601
+ super()
602
+ self.io = io
603
+ self.options = options
604
+ end
605
+ end
606
+
607
+ ##
608
+ # A very simple reporter that prints the "dots" during the run.
609
+ #
610
+ # This is added to the top-level CompositeReporter at the start of
611
+ # the run. If you want to change the output of minitest via a
612
+ # plugin, pull this out of the composite and replace it with your
613
+ # own.
614
+
615
+ class ProgressReporter < Reporter
616
+ def prerecord klass, name #:nodoc:
617
+ if options[:verbose] then
618
+ io.print "%s#%s = " % [klass.name, name]
619
+ io.flush
620
+ end
621
+ end
622
+
623
+ def record result # :nodoc:
624
+ io.print "%.2f s = " % [result.time] if options[:verbose]
625
+ io.print result.result_code
626
+ io.puts if options[:verbose]
627
+ end
628
+ end
629
+
630
+ ##
631
+ # A reporter that gathers statistics about a test run. Does not do
632
+ # any IO because meant to be used as a parent class for a reporter
633
+ # that does.
634
+ #
635
+ # If you want to create an entirely different type of output (eg,
636
+ # CI, HTML, etc), this is the place to start.
637
+ #
638
+ # Example:
639
+ #
640
+ # class JenkinsCIReporter < StatisticsReporter
641
+ # def report
642
+ # super # Needed to calculate some statistics
643
+ #
644
+ # print "<testsuite "
645
+ # print "tests='#{count}' "
646
+ # print "failures='#{failures}' "
647
+ # # Remaining XML...
648
+ # end
649
+ # end
650
+
651
+ class StatisticsReporter < Reporter
652
+ ##
653
+ # Total number of assertions.
654
+
655
+ attr_accessor :assertions
656
+
657
+ ##
658
+ # Total number of test cases.
659
+
660
+ attr_accessor :count
661
+
662
+ ##
663
+ # An +Array+ of test cases that failed or were skipped.
664
+
665
+ attr_accessor :results
666
+
667
+ ##
668
+ # Time the test run started. If available, the monotonic clock is
669
+ # used and this is a +Float+, otherwise it's an instance of
670
+ # +Time+.
671
+
672
+ attr_accessor :start_time
673
+
674
+ ##
675
+ # Test run time. If available, the monotonic clock is used and
676
+ # this is a +Float+, otherwise it's an instance of +Time+.
677
+
678
+ attr_accessor :total_time
679
+
680
+ ##
681
+ # Total number of tests that failed.
682
+
683
+ attr_accessor :failures
684
+
685
+ ##
686
+ # Total number of tests that erred.
687
+
688
+ attr_accessor :errors
689
+
690
+ ##
691
+ # Total number of tests that where skipped.
692
+
693
+ attr_accessor :skips
694
+
695
+ def initialize io = $stdout, options = {} # :nodoc:
696
+ super
697
+
698
+ self.assertions = 0
699
+ self.count = 0
700
+ self.results = []
701
+ self.start_time = nil
702
+ self.total_time = nil
703
+ self.failures = nil
704
+ self.errors = nil
705
+ self.skips = nil
706
+ end
707
+
708
+ def passed? # :nodoc:
709
+ results.all?(&:skipped?)
710
+ end
711
+
712
+ def start # :nodoc:
713
+ self.start_time = Minitest.clock_time
714
+ end
715
+
716
+ def record result # :nodoc:
717
+ self.count += 1
718
+ self.assertions += result.assertions
719
+
720
+ results << result if not result.passed? or result.skipped?
721
+ end
722
+
723
+ ##
724
+ # Report on the tracked statistics.
725
+
726
+ def report
727
+ aggregate = results.group_by { |r| r.failure.class }
728
+ aggregate.default = [] # dumb. group_by should provide this
729
+
730
+ self.total_time = Minitest.clock_time - start_time
731
+ self.failures = aggregate[Assertion].size
732
+ self.errors = aggregate[UnexpectedError].size
733
+ self.skips = aggregate[Skip].size
734
+ end
735
+ end
736
+
737
+ ##
738
+ # A reporter that prints the header, summary, and failure details at
739
+ # the end of the run.
740
+ #
741
+ # This is added to the top-level CompositeReporter at the start of
742
+ # the run. If you want to change the output of minitest via a
743
+ # plugin, pull this out of the composite and replace it with your
744
+ # own.
745
+
746
+ class SummaryReporter < StatisticsReporter
747
+ # :stopdoc:
748
+ attr_accessor :sync
749
+ attr_accessor :old_sync
750
+ # :startdoc:
751
+
752
+ def start # :nodoc:
753
+ super
754
+
755
+ io.puts "Run options: #{options[:args]}"
756
+ io.puts
757
+ io.puts "# Running:"
758
+ io.puts
759
+
760
+ self.sync = io.respond_to? :"sync=" # stupid emacs
761
+ self.old_sync, io.sync = io.sync, true if self.sync
762
+ end
763
+
764
+ def report # :nodoc:
765
+ super
766
+
767
+ io.sync = self.old_sync
768
+
769
+ io.puts unless options[:verbose] # finish the dots
770
+ io.puts
771
+ io.puts statistics
772
+ aggregated_results io
773
+ io.puts summary
774
+ end
775
+
776
+ def statistics # :nodoc:
777
+ "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." %
778
+ [total_time, count / total_time, assertions / total_time]
779
+ end
780
+
781
+ def aggregated_results io # :nodoc:
782
+ filtered_results = results.dup
783
+ filtered_results.reject!(&:skipped?) unless options[:verbose]
784
+
785
+ filtered_results.each_with_index { |result, i|
786
+ io.puts "\n%3d) %s" % [i+1, result]
787
+ }
788
+ io.puts
789
+ io
790
+ end
791
+
792
+ def to_s # :nodoc:
793
+ aggregated_results(StringIO.new(binary_string)).string
794
+ end
795
+
796
+ def summary # :nodoc:
797
+ extra = ""
798
+
799
+ extra = "\n\nYou have skipped tests. Run with --verbose for details." if
800
+ results.any?(&:skipped?) unless options[:verbose] or ENV["MT_NO_SKIP_MSG"]
801
+
802
+ "%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
803
+ [count, assertions, failures, errors, skips, extra]
804
+ end
805
+
806
+ private
807
+
808
+ if '<3'.respond_to? :b
809
+ def binary_string; ''.b; end
810
+ else
811
+ def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end
812
+ end
813
+ end
814
+
815
+ ##
816
+ # Dispatch to multiple reporters as one.
817
+
818
+ class CompositeReporter < AbstractReporter
819
+ ##
820
+ # The list of reporters to dispatch to.
821
+
822
+ attr_accessor :reporters
823
+
824
+ def initialize *reporters # :nodoc:
825
+ super()
826
+ self.reporters = reporters
827
+ end
828
+
829
+ def io # :nodoc:
830
+ reporters.first.io
831
+ end
832
+
833
+ ##
834
+ # Add another reporter to the mix.
835
+
836
+ def << reporter
837
+ self.reporters << reporter
838
+ end
839
+
840
+ def passed? # :nodoc:
841
+ self.reporters.all?(&:passed?)
842
+ end
843
+
844
+ def start # :nodoc:
845
+ self.reporters.each(&:start)
846
+ end
847
+
848
+ def prerecord klass, name # :nodoc:
849
+ self.reporters.each do |reporter|
850
+ # TODO: remove conditional for minitest 6
851
+ reporter.prerecord klass, name if reporter.respond_to? :prerecord
852
+ end
853
+ end
854
+
855
+ def record result # :nodoc:
856
+ self.reporters.each do |reporter|
857
+ reporter.record result
858
+ end
859
+ end
860
+
861
+ def report # :nodoc:
862
+ self.reporters.each(&:report)
863
+ end
864
+ end
865
+
866
+ ##
867
+ # Represents run failures.
868
+
869
+ class Assertion < Exception
870
+ def error # :nodoc:
871
+ self
872
+ end
873
+
874
+ ##
875
+ # Where was this run before an assertion was raised?
876
+
877
+ def location
878
+ last_before_assertion = ""
879
+ self.backtrace.reverse_each do |s|
880
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
881
+ last_before_assertion = s
882
+ end
883
+ last_before_assertion.sub(/:in .*$/, "")
884
+ end
885
+
886
+ def result_code # :nodoc:
887
+ result_label[0, 1]
888
+ end
889
+
890
+ def result_label # :nodoc:
891
+ "Failure"
892
+ end
893
+ end
894
+
895
+ ##
896
+ # Assertion raised when skipping a run.
897
+
898
+ class Skip < Assertion
899
+ def result_label # :nodoc:
900
+ "Skipped"
901
+ end
902
+ end
903
+
904
+ ##
905
+ # Assertion wrapping an unexpected error that was raised during a run.
906
+
907
+ class UnexpectedError < Assertion
908
+ attr_accessor :exception # :nodoc:
909
+
910
+ def initialize exception # :nodoc:
911
+ super "Unexpected exception"
912
+ self.exception = exception
913
+ end
914
+
915
+ def backtrace # :nodoc:
916
+ self.exception.backtrace
917
+ end
918
+
919
+ def error # :nodoc:
920
+ self.exception
921
+ end
922
+
923
+ def message # :nodoc:
924
+ bt = Minitest.filter_backtrace(self.backtrace).join "\n "
925
+ "#{self.exception.class}: #{self.exception.message}\n #{bt}"
926
+ end
927
+
928
+ def result_label # :nodoc:
929
+ "Error"
930
+ end
931
+ end
932
+
933
+ ##
934
+ # Provides a simple set of guards that you can use in your tests
935
+ # to skip execution if it is not applicable. These methods are
936
+ # mixed into Test as both instance and class methods so you
937
+ # can use them inside or outside of the test methods.
938
+ #
939
+ # def test_something_for_mri
940
+ # skip "bug 1234" if jruby?
941
+ # # ...
942
+ # end
943
+ #
944
+ # if windows? then
945
+ # # ... lots of test methods ...
946
+ # end
947
+
948
+ module Guard
949
+
950
+ ##
951
+ # Is this running on jruby?
952
+
953
+ def jruby? platform = RUBY_PLATFORM
954
+ "java" == platform
955
+ end
956
+
957
+ ##
958
+ # Is this running on maglev?
959
+
960
+ def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
961
+ "maglev" == platform
962
+ end
963
+
964
+ ##
965
+ # Is this running on mri?
966
+
967
+ def mri? platform = RUBY_DESCRIPTION
968
+ /^ruby/ =~ platform
969
+ end
970
+
971
+ ##
972
+ # Is this running on rubinius?
973
+
974
+ def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
975
+ "rbx" == platform
976
+ end
977
+
978
+ ##
979
+ # Is this running on windows?
980
+
981
+ def windows? platform = RUBY_PLATFORM
982
+ /mswin|mingw/ =~ platform
983
+ end
984
+ end
985
+
986
+ ##
987
+ # The standard backtrace filter for minitest.
988
+ #
989
+ # See Minitest.backtrace_filter=.
990
+
991
+ class BacktraceFilter
992
+
993
+ MT_RE = %r%lib/minitest% #:nodoc:
994
+
995
+ ##
996
+ # Filter +bt+ to something useful. Returns the whole thing if $DEBUG.
997
+
998
+ def filter bt
999
+ return ["No backtrace"] unless bt
1000
+
1001
+ return bt.dup if $DEBUG
1002
+
1003
+ new_bt = bt.take_while { |line| line !~ MT_RE }
1004
+ new_bt = bt.select { |line| line !~ MT_RE } if new_bt.empty?
1005
+ new_bt = bt.dup if new_bt.empty?
1006
+
1007
+ new_bt
1008
+ end
1009
+ end
1010
+
1011
+ self.backtrace_filter = BacktraceFilter.new
1012
+
1013
+ def self.run_one_method klass, method_name # :nodoc:
1014
+ result = klass.new(method_name).run
1015
+ raise "#{klass}#run _must_ return a Result" unless Result === result
1016
+ result
1017
+ end
1018
+
1019
+ # :stopdoc:
1020
+
1021
+ if defined? Process::CLOCK_MONOTONIC # :nodoc:
1022
+ def self.clock_time
1023
+ Process.clock_gettime Process::CLOCK_MONOTONIC
1024
+ end
1025
+ else
1026
+ def self.clock_time
1027
+ Time.now
1028
+ end
1029
+ end
1030
+
1031
+ class Runnable # re-open
1032
+ def self.inherited klass # :nodoc:
1033
+ self.runnables << klass
1034
+ super
1035
+ end
1036
+ end
1037
+
1038
+ # :startdoc:
1039
+ end
1040
+
1041
+ require "minitest/test"