minitest 5.11.2

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