minitest 5.10.3 → 5.15.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.
@@ -53,7 +53,7 @@ module Minitest
53
53
  end
54
54
  end
55
55
 
56
- module Test
56
+ module Test # :nodoc:
57
57
  def _synchronize; Minitest::Test.io_lock.synchronize { yield }; end # :nodoc:
58
58
 
59
59
  module ClassMethods # :nodoc:
data/lib/minitest/spec.rb CHANGED
@@ -4,16 +4,21 @@ class Module # :nodoc:
4
4
  def infect_an_assertion meth, new_name, dont_flip = false # :nodoc:
5
5
  block = dont_flip == :block
6
6
  dont_flip = false if block
7
+ target_obj = block ? '_{obj.method}' : '_(obj)'
7
8
 
8
9
  # warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
9
10
  self.class_eval <<-EOM, __FILE__, __LINE__ + 1
10
11
  def #{new_name} *args
12
+ where = Minitest.filter_backtrace(caller).first
13
+ where = where.split(/:in /, 2).first # clean up noise
14
+ Kernel.warn "DEPRECATED: global use of #{new_name} from #\{where}. Use #{target_obj}.#{new_name} instead. This will fail in Minitest 6."
11
15
  Minitest::Expectation.new(self, Minitest::Spec.current).#{new_name}(*args)
12
16
  end
13
17
  EOM
14
18
 
15
19
  Minitest::Expectation.class_eval <<-EOM, __FILE__, __LINE__ + 1
16
20
  def #{new_name} *args
21
+ raise "Calling ##{new_name} outside of test." unless ctx
17
22
  case
18
23
  when #{!!dont_flip} then
19
24
  ctx.#{meth}(target, *args)
@@ -285,21 +290,28 @@ class Minitest::Spec < Minitest::Test
285
290
 
286
291
  module InstanceMethods
287
292
  ##
288
- # Returns a value monad that has all of Expectations methods
289
- # available to it.
293
+ # Takes a value or a block and returns a value monad that has
294
+ # all of Expectations methods available to it.
290
295
  #
291
- # Also aliased to #value and #expect for your aesthetic pleasure:
296
+ # _(1 + 1).must_equal 2
292
297
  #
293
- # _(1 + 1).must_equal 2
294
- # value(1 + 1).must_equal 2
295
- # expect(1 + 1).must_equal 2
298
+ # And for blocks:
299
+ #
300
+ # _ { 1 + "1" }.must_raise TypeError
296
301
  #
297
302
  # This method of expectation-based testing is preferable to
298
303
  # straight-expectation methods (on Object) because it stores its
299
304
  # test context, bypassing our hacky use of thread-local variables.
300
305
  #
301
- # At some point, the methods on Object will be deprecated and then
302
- # removed.
306
+ # NOTE: At some point, the methods on Object will be deprecated
307
+ # and then removed.
308
+ #
309
+ # It is also aliased to #value and #expect for your aesthetic
310
+ # pleasure:
311
+ #
312
+ # _(1 + 1).must_equal 2
313
+ # value(1 + 1).must_equal 2
314
+ # expect(1 + 1).must_equal 2
303
315
 
304
316
  def _ value = nil, &block
305
317
  Minitest::Expectation.new block || value, self
data/lib/minitest/test.rb CHANGED
@@ -10,6 +10,11 @@ module Minitest
10
10
  class Test < Runnable
11
11
  require "minitest/assertions"
12
12
  include Minitest::Assertions
13
+ include Minitest::Reportable
14
+
15
+ def class_name # :nodoc:
16
+ self.class.name # for Minitest::Reportable
17
+ end
13
18
 
14
19
  PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, SystemExit] # :nodoc:
15
20
 
@@ -79,20 +84,6 @@ module Minitest
79
84
  :random
80
85
  end
81
86
 
82
- ##
83
- # The time it took to run this test.
84
-
85
- attr_accessor :time
86
-
87
- def marshal_dump # :nodoc:
88
- super << self.time
89
- end
90
-
91
- def marshal_load ary # :nodoc:
92
- self.time = ary.pop
93
- super
94
- end
95
-
96
87
  TEARDOWN_METHODS = %w[ before_teardown teardown after_teardown ] # :nodoc:
97
88
 
98
89
  ##
@@ -115,7 +106,7 @@ module Minitest
115
106
  end
116
107
  end
117
108
 
118
- self # per contract
109
+ Result.from self # per contract
119
110
  end
120
111
 
121
112
  ##
@@ -207,62 +198,17 @@ module Minitest
207
198
  rescue Assertion => e
208
199
  self.failures << e
209
200
  rescue Exception => e
210
- self.failures << UnexpectedError.new(e)
201
+ self.failures << UnexpectedError.new(sanitize_exception e)
211
202
  end
212
203
 
213
- ##
214
- # Did this run error?
215
-
216
- def error?
217
- self.failures.any? { |f| UnexpectedError === f }
218
- end
219
-
220
- ##
221
- # The location identifier of this test.
222
-
223
- def location
224
- loc = " [#{self.failure.location}]" unless passed? or error?
225
- "#{self.class}##{self.name}#{loc}"
226
- end
227
-
228
- ##
229
- # Did this run pass?
230
- #
231
- # Note: skipped runs are not considered passing, but they don't
232
- # cause the process to exit non-zero.
233
-
234
- def passed?
235
- not self.failure
236
- end
237
-
238
- ##
239
- # Returns ".", "F", or "E" based on the result of the run.
240
-
241
- def result_code
242
- self.failure and self.failure.result_code or "."
243
- end
244
-
245
- ##
246
- # Was this run skipped?
247
-
248
- def skipped?
249
- self.failure and Skip === self.failure
250
- end
251
-
252
- def time_it # :nodoc:
253
- t0 = Minitest.clock_time
254
-
255
- yield
256
- ensure
257
- self.time = Minitest.clock_time - t0
258
- end
259
-
260
- def to_s # :nodoc:
261
- return location if passed? and not skipped?
262
-
263
- failures.map { |failure|
264
- "#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n"
265
- }.join "\n"
204
+ def sanitize_exception e # :nodoc:
205
+ Marshal.dump e
206
+ e
207
+ rescue TypeError
208
+ bt = e.backtrace
209
+ e = RuntimeError.new "Wrapped undumpable exception for: #{e.class}: #{e.message}"
210
+ e.set_backtrace bt
211
+ e
266
212
  end
267
213
 
268
214
  def with_info_handler &block # :nodoc:
data/lib/minitest.rb CHANGED
@@ -3,12 +3,13 @@ require "thread"
3
3
  require "mutex_m"
4
4
  require "minitest/parallel"
5
5
  require "stringio"
6
+ require "etc"
6
7
 
7
8
  ##
8
9
  # :include: README.rdoc
9
10
 
10
11
  module Minitest
11
- VERSION = "5.10.3" # :nodoc:
12
+ VERSION = "5.15.0" # :nodoc:
12
13
  ENCS = "".respond_to? :encoding # :nodoc:
13
14
 
14
15
  @@installed_at_exit ||= false
@@ -21,7 +22,10 @@ module Minitest
21
22
  # Parallel test executor
22
23
 
23
24
  mc.send :attr_accessor, :parallel_executor
24
- self.parallel_executor = Parallel::Executor.new((ENV["N"] || 2).to_i)
25
+
26
+ warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"]
27
+ n_threads = (ENV["MT_CPU"] || ENV["N"] || Etc.nprocessors).to_i
28
+ self.parallel_executor = Parallel::Executor.new n_threads
25
29
 
26
30
  ##
27
31
  # Filter object for backtraces.
@@ -50,12 +54,18 @@ module Minitest
50
54
  # Registers Minitest to run at process exit
51
55
 
52
56
  def self.autorun
57
+ if Object.const_defined?(:Warning) && Warning.respond_to?(:[]=)
58
+ Warning[:deprecated] = true
59
+ end
60
+
53
61
  at_exit {
54
62
  next if $! and not ($!.kind_of? SystemExit and $!.success?)
55
63
 
56
64
  exit_code = nil
57
65
 
66
+ pid = Process.pid
58
67
  at_exit {
68
+ next if Process.pid != pid
59
69
  @@after_run.reverse_each(&:call)
60
70
  exit exit_code || false
61
71
  }
@@ -118,7 +128,7 @@ module Minitest
118
128
  # klass.new(runnable_method).run
119
129
 
120
130
  def self.run args = []
121
- self.load_plugins
131
+ self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
122
132
 
123
133
  options = process_args args
124
134
 
@@ -175,6 +185,8 @@ module Minitest
175
185
  exit
176
186
  end
177
187
 
188
+ opts.on "--no-plugins", "Bypass minitest plugin auto-loading (or set $MT_NO_PLUGINS)."
189
+
178
190
  desc = "Sets random seed. Also via env. Eg: SEED=n rake"
179
191
  opts.on "-s", "--seed SEED", Integer, desc do |m|
180
192
  options[:seed] = m.to_i
@@ -192,6 +204,10 @@ module Minitest
192
204
  options[:exclude] = a
193
205
  end
194
206
 
207
+ opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s|
208
+ options[:skip] = s.chars.to_a
209
+ end
210
+
195
211
  unless extensions.empty?
196
212
  opts.separator ""
197
213
  opts.separator "Known extensions: #{extensions.join(", ")}"
@@ -231,7 +247,9 @@ module Minitest
231
247
  end
232
248
 
233
249
  def self.filter_backtrace bt # :nodoc:
234
- backtrace_filter.filter bt
250
+ result = backtrace_filter.filter bt
251
+ result = bt.dup if result.empty?
252
+ result
235
253
  end
236
254
 
237
255
  ##
@@ -252,6 +270,19 @@ module Minitest
252
270
 
253
271
  attr_accessor :failures
254
272
 
273
+ ##
274
+ # The time it took to run.
275
+
276
+ attr_accessor :time
277
+
278
+ def time_it # :nodoc:
279
+ t0 = Minitest.clock_time
280
+
281
+ yield
282
+ ensure
283
+ self.time = Minitest.clock_time - t0
284
+ end
285
+
255
286
  ##
256
287
  # Name of the run.
257
288
 
@@ -266,11 +297,6 @@ module Minitest
266
297
  @NAME = o
267
298
  end
268
299
 
269
- def self.inherited klass # :nodoc:
270
- self.runnables << klass
271
- super
272
- end
273
-
274
300
  ##
275
301
  # Returns all instance methods matching the pattern +re+.
276
302
 
@@ -291,7 +317,7 @@ module Minitest
291
317
 
292
318
  def self.run reporter, options = {}
293
319
  filter = options[:filter] || "/./"
294
- filter = Regexp.new $1 if filter =~ %r%/(.*)/%
320
+ filter = Regexp.new $1 if filter.is_a?(String) && filter =~ %r%/(.*)/%
295
321
 
296
322
  filtered_methods = self.runnable_methods.find_all { |m|
297
323
  filter === m || filter === "#{self}##{m}"
@@ -367,12 +393,20 @@ module Minitest
367
393
  @@runnables
368
394
  end
369
395
 
396
+ @@marshal_dump_warned = false
397
+
370
398
  def marshal_dump # :nodoc:
371
- [self.name, self.failures, self.assertions]
399
+ unless @@marshal_dump_warned then
400
+ warn ["Minitest::Runnable#marshal_dump is deprecated.",
401
+ "You might be violating internals. From", caller.first].join " "
402
+ @@marshal_dump_warned = true
403
+ end
404
+
405
+ [self.name, self.failures, self.assertions, self.time]
372
406
  end
373
407
 
374
408
  def marshal_load ary # :nodoc:
375
- self.name, self.failures, self.assertions = ary
409
+ self.name, self.failures, self.assertions, self.time = ary
376
410
  end
377
411
 
378
412
  def failure # :nodoc:
@@ -404,7 +438,8 @@ module Minitest
404
438
 
405
439
  ##
406
440
  # Returns a single character string to print based on the result
407
- # of the run. Eg ".", "F", or "E".
441
+ # of the run. One of <tt>"."</tt>, <tt>"F"</tt>,
442
+ # <tt>"E"</tt> or <tt>"S"</tt>.
408
443
 
409
444
  def result_code
410
445
  raise NotImplementedError, "subclass responsibility"
@@ -418,6 +453,109 @@ module Minitest
418
453
  end
419
454
  end
420
455
 
456
+ ##
457
+ # Shared code for anything that can get passed to a Reporter. See
458
+ # Minitest::Test & Minitest::Result.
459
+
460
+ module Reportable
461
+ ##
462
+ # Did this run pass?
463
+ #
464
+ # Note: skipped runs are not considered passing, but they don't
465
+ # cause the process to exit non-zero.
466
+
467
+ def passed?
468
+ not self.failure
469
+ end
470
+
471
+ ##
472
+ # The location identifier of this test. Depends on a method
473
+ # existing called class_name.
474
+
475
+ def location
476
+ loc = " [#{self.failure.location}]" unless passed? or error?
477
+ "#{self.class_name}##{self.name}#{loc}"
478
+ end
479
+
480
+ def class_name # :nodoc:
481
+ raise NotImplementedError, "subclass responsibility"
482
+ end
483
+
484
+ ##
485
+ # Returns ".", "F", or "E" based on the result of the run.
486
+
487
+ def result_code
488
+ self.failure and self.failure.result_code or "."
489
+ end
490
+
491
+ ##
492
+ # Was this run skipped?
493
+
494
+ def skipped?
495
+ self.failure and Skip === self.failure
496
+ end
497
+
498
+ ##
499
+ # Did this run error?
500
+
501
+ def error?
502
+ self.failures.any? { |f| UnexpectedError === f }
503
+ end
504
+ end
505
+
506
+ ##
507
+ # This represents a test result in a clean way that can be
508
+ # marshalled over a wire. Tests can do anything they want to the
509
+ # test instance and can create conditions that cause Marshal.dump to
510
+ # blow up. By using Result.from(a_test) you can be reasonably sure
511
+ # that the test result can be marshalled.
512
+
513
+ class Result < Runnable
514
+ include Minitest::Reportable
515
+
516
+ undef_method :marshal_dump
517
+ undef_method :marshal_load
518
+
519
+ ##
520
+ # The class name of the test result.
521
+
522
+ attr_accessor :klass
523
+
524
+ ##
525
+ # The location of the test method.
526
+
527
+ attr_accessor :source_location
528
+
529
+ ##
530
+ # Create a new test result from a Runnable instance.
531
+
532
+ def self.from runnable
533
+ o = runnable
534
+
535
+ r = self.new o.name
536
+ r.klass = o.class.name
537
+ r.assertions = o.assertions
538
+ r.failures = o.failures.dup
539
+ r.time = o.time
540
+
541
+ r.source_location = o.method(o.name).source_location rescue ["unknown", -1]
542
+
543
+ r
544
+ end
545
+
546
+ def class_name # :nodoc:
547
+ self.klass # for Minitest::Reportable
548
+ end
549
+
550
+ def to_s # :nodoc:
551
+ return location if passed? and not skipped?
552
+
553
+ failures.map { |failure|
554
+ "#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n"
555
+ }.join "\n"
556
+ end
557
+ end
558
+
421
559
  ##
422
560
  # Defines the API for Reporters. Subclass this and override whatever
423
561
  # you want. Go nuts.
@@ -439,8 +577,10 @@ module Minitest
439
577
  end
440
578
 
441
579
  ##
442
- # Record a result and output the Runnable#result_code. Stores the
443
- # result of the run if the run did not pass.
580
+ # Output and record the result of the test. Call
581
+ # {result#result_code}[rdoc-ref:Runnable#result_code] to get the
582
+ # result character string. Stores the result of the run if the run
583
+ # did not pass.
444
584
 
445
585
  def record result
446
586
  end
@@ -488,7 +628,7 @@ module Minitest
488
628
  class ProgressReporter < Reporter
489
629
  def prerecord klass, name #:nodoc:
490
630
  if options[:verbose] then
491
- io.print "%s#%s = " % [klass, name]
631
+ io.print "%s#%s = " % [klass.name, name]
492
632
  io.flush
493
633
  end
494
634
  end
@@ -507,18 +647,63 @@ module Minitest
507
647
  #
508
648
  # If you want to create an entirely different type of output (eg,
509
649
  # CI, HTML, etc), this is the place to start.
650
+ #
651
+ # Example:
652
+ #
653
+ # class JenkinsCIReporter < StatisticsReporter
654
+ # def report
655
+ # super # Needed to calculate some statistics
656
+ #
657
+ # print "<testsuite "
658
+ # print "tests='#{count}' "
659
+ # print "failures='#{failures}' "
660
+ # # Remaining XML...
661
+ # end
662
+ # end
510
663
 
511
664
  class StatisticsReporter < Reporter
512
- # :stopdoc:
665
+ ##
666
+ # Total number of assertions.
667
+
513
668
  attr_accessor :assertions
669
+
670
+ ##
671
+ # Total number of test cases.
672
+
514
673
  attr_accessor :count
674
+
675
+ ##
676
+ # An +Array+ of test cases that failed or were skipped.
677
+
515
678
  attr_accessor :results
679
+
680
+ ##
681
+ # Time the test run started. If available, the monotonic clock is
682
+ # used and this is a +Float+, otherwise it's an instance of
683
+ # +Time+.
684
+
516
685
  attr_accessor :start_time
686
+
687
+ ##
688
+ # Test run time. If available, the monotonic clock is used and
689
+ # this is a +Float+, otherwise it's an instance of +Time+.
690
+
517
691
  attr_accessor :total_time
692
+
693
+ ##
694
+ # Total number of tests that failed.
695
+
518
696
  attr_accessor :failures
697
+
698
+ ##
699
+ # Total number of tests that erred.
700
+
519
701
  attr_accessor :errors
702
+
703
+ ##
704
+ # Total number of tests that where skipped.
705
+
520
706
  attr_accessor :skips
521
- # :startdoc:
522
707
 
523
708
  def initialize io = $stdout, options = {} # :nodoc:
524
709
  super
@@ -548,7 +733,10 @@ module Minitest
548
733
  results << result if not result.passed? or result.skipped?
549
734
  end
550
735
 
551
- def report # :nodoc:
736
+ ##
737
+ # Report on the tracked statistics.
738
+
739
+ def report
552
740
  aggregate = results.group_by { |r| r.failure.class }
553
741
  aggregate.default = [] # dumb. group_by should provide this
554
742
 
@@ -607,7 +795,11 @@ module Minitest
607
795
  filtered_results = results.dup
608
796
  filtered_results.reject!(&:skipped?) unless options[:verbose]
609
797
 
798
+ skip = options[:skip] || []
799
+
610
800
  filtered_results.each_with_index { |result, i|
801
+ next if skip.include? result.result_code
802
+
611
803
  io.puts "\n%3d) %s" % [i+1, result]
612
804
  }
613
805
  io.puts
@@ -730,24 +922,21 @@ module Minitest
730
922
  # Assertion wrapping an unexpected error that was raised during a run.
731
923
 
732
924
  class UnexpectedError < Assertion
733
- attr_accessor :exception # :nodoc:
925
+ # TODO: figure out how to use `cause` instead
926
+ attr_accessor :error # :nodoc:
734
927
 
735
- def initialize exception # :nodoc:
928
+ def initialize error # :nodoc:
736
929
  super "Unexpected exception"
737
- self.exception = exception
930
+ self.error = error
738
931
  end
739
932
 
740
933
  def backtrace # :nodoc:
741
- self.exception.backtrace
742
- end
743
-
744
- def error # :nodoc:
745
- self.exception
934
+ self.error.backtrace
746
935
  end
747
936
 
748
937
  def message # :nodoc:
749
938
  bt = Minitest.filter_backtrace(self.backtrace).join "\n "
750
- "#{self.exception.class}: #{self.exception.message}\n #{bt}"
939
+ "#{self.error.class}: #{self.error.message}\n #{bt}"
751
940
  end
752
941
 
753
942
  def result_label # :nodoc:
@@ -783,6 +972,9 @@ module Minitest
783
972
  # Is this running on maglev?
784
973
 
785
974
  def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
975
+ where = Minitest.filter_backtrace(caller).first
976
+ where = where.split(/:in /, 2).first # clean up noise
977
+ warn "DEPRECATED: `maglev?` called from #{where}. This will fail in Minitest 6."
786
978
  "maglev" == platform
787
979
  end
788
980
 
@@ -793,10 +985,20 @@ module Minitest
793
985
  /^ruby/ =~ platform
794
986
  end
795
987
 
988
+ ##
989
+ # Is this running on macOS?
990
+
991
+ def osx? platform = RUBY_PLATFORM
992
+ /darwin/ =~ platform
993
+ end
994
+
796
995
  ##
797
996
  # Is this running on rubinius?
798
997
 
799
998
  def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
999
+ where = Minitest.filter_backtrace(caller).first
1000
+ where = where.split(/:in /, 2).first # clean up noise
1001
+ warn "DEPRECATED: `rubinius?` called from #{where}. This will fail in Minitest 6."
800
1002
  "rbx" == platform
801
1003
  end
802
1004
 
@@ -818,12 +1020,13 @@ module Minitest
818
1020
  MT_RE = %r%lib/minitest% #:nodoc:
819
1021
 
820
1022
  ##
821
- # Filter +bt+ to something useful. Returns the whole thing if $DEBUG.
1023
+ # Filter +bt+ to something useful. Returns the whole thing if
1024
+ # $DEBUG (ruby) or $MT_DEBUG (env).
822
1025
 
823
1026
  def filter bt
824
1027
  return ["No backtrace"] unless bt
825
1028
 
826
- return bt.dup if $DEBUG
1029
+ return bt.dup if $DEBUG || ENV["MT_DEBUG"]
827
1030
 
828
1031
  new_bt = bt.take_while { |line| line !~ MT_RE }
829
1032
  new_bt = bt.select { |line| line !~ MT_RE } if new_bt.empty?
@@ -837,7 +1040,7 @@ module Minitest
837
1040
 
838
1041
  def self.run_one_method klass, method_name # :nodoc:
839
1042
  result = klass.new(method_name).run
840
- raise "#{klass}#run _must_ return self" unless klass === result
1043
+ raise "#{klass}#run _must_ return a Result" unless Result === result
841
1044
  result
842
1045
  end
843
1046
 
@@ -853,6 +1056,13 @@ module Minitest
853
1056
  end
854
1057
  end
855
1058
 
1059
+ class Runnable # re-open
1060
+ def self.inherited klass # :nodoc:
1061
+ self.runnables << klass
1062
+ super
1063
+ end
1064
+ end
1065
+
856
1066
  # :startdoc:
857
1067
  end
858
1068