minitest 5.11.3 → 5.17.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/minitest.rb CHANGED
@@ -3,59 +3,79 @@ 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.11.3" # :nodoc:
12
- ENCS = "".respond_to? :encoding # :nodoc:
12
+ VERSION = "5.17.0" # :nodoc:
13
13
 
14
14
  @@installed_at_exit ||= false
15
15
  @@after_run = []
16
16
  @extensions = []
17
17
 
18
- mc = (class << self; self; end)
18
+ def self.cattr_accessor name # :nodoc:
19
+ (class << self; self; end).attr_accessor name
20
+ end
21
+
22
+ ##
23
+ # The random seed used for this run. This is used to srand at the
24
+ # start of the run and between each +Runnable.run+.
25
+ #
26
+ # Set via Minitest.run after processing args.
27
+
28
+ cattr_accessor :seed
19
29
 
20
30
  ##
21
31
  # Parallel test executor
22
32
 
23
- mc.send :attr_accessor, :parallel_executor
24
- self.parallel_executor = Parallel::Executor.new((ENV["N"] || 2).to_i)
33
+ cattr_accessor :parallel_executor
34
+
35
+ warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"]
36
+ n_threads = (ENV["MT_CPU"] || ENV["N"] || Etc.nprocessors).to_i
37
+
38
+ self.parallel_executor = Parallel::Executor.new n_threads
25
39
 
26
40
  ##
27
41
  # Filter object for backtraces.
28
42
 
29
- mc.send :attr_accessor, :backtrace_filter
43
+ cattr_accessor :backtrace_filter
30
44
 
31
45
  ##
32
46
  # Reporter object to be used for all runs.
33
47
  #
34
48
  # NOTE: This accessor is only available during setup, not during runs.
35
49
 
36
- mc.send :attr_accessor, :reporter
50
+ cattr_accessor :reporter
37
51
 
38
52
  ##
39
53
  # Names of known extension plugins.
40
54
 
41
- mc.send :attr_accessor, :extensions
55
+ cattr_accessor :extensions
42
56
 
43
57
  ##
44
58
  # The signal to use for dumping information to STDERR. Defaults to "INFO".
45
59
 
46
- mc.send :attr_accessor, :info_signal
60
+ cattr_accessor :info_signal
47
61
  self.info_signal = "INFO"
48
62
 
49
63
  ##
50
64
  # Registers Minitest to run at process exit
51
65
 
52
66
  def self.autorun
67
+ if Object.const_defined?(:Warning) && Warning.respond_to?(:[]=)
68
+ Warning[:deprecated] = true
69
+ end
70
+
53
71
  at_exit {
54
72
  next if $! and not ($!.kind_of? SystemExit and $!.success?)
55
73
 
56
74
  exit_code = nil
57
75
 
76
+ pid = Process.pid
58
77
  at_exit {
78
+ next if Process.pid != pid
59
79
  @@after_run.reverse_each(&:call)
60
80
  exit exit_code || false
61
81
  }
@@ -122,6 +142,9 @@ module Minitest
122
142
 
123
143
  options = process_args args
124
144
 
145
+ Minitest.seed = options[:seed]
146
+ srand Minitest.seed
147
+
125
148
  reporter = CompositeReporter.new
126
149
  reporter << SummaryReporter.new(options[:io], options)
127
150
  reporter << ProgressReporter.new(options[:io], options)
@@ -148,7 +171,7 @@ module Minitest
148
171
  # sub-classes to run.
149
172
 
150
173
  def self.__run reporter, options
151
- suites = Runnable.runnables.reject { |s| s.runnable_methods.empty? }.shuffle
174
+ suites = Runnable.runnables.shuffle
152
175
  parallel, serial = suites.partition { |s| s.test_order == :parallel }
153
176
 
154
177
  # If we run the parallel tests before the serial tests, the parallel tests
@@ -186,6 +209,10 @@ module Minitest
186
209
  options[:verbose] = true
187
210
  end
188
211
 
212
+ opts.on "--show-skips", "Show skipped at the end of run." do
213
+ options[:show_skips] = true
214
+ end
215
+
189
216
  opts.on "-n", "--name PATTERN", "Filter run on /regexp/ or string." do |a|
190
217
  options[:filter] = a
191
218
  end
@@ -194,6 +221,10 @@ module Minitest
194
221
  options[:exclude] = a
195
222
  end
196
223
 
224
+ opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s|
225
+ options[:skip] = s.chars.to_a
226
+ end
227
+
197
228
  unless extensions.empty?
198
229
  opts.separator ""
199
230
  opts.separator "Known extensions: #{extensions.join(", ")}"
@@ -223,8 +254,6 @@ module Minitest
223
254
  orig_args << "--seed" << options[:seed].to_s
224
255
  end
225
256
 
226
- srand options[:seed]
227
-
228
257
  options[:args] = orig_args.map { |s|
229
258
  s =~ /[\s|&<>$()]/ ? s.inspect : s
230
259
  }.join " "
@@ -233,7 +262,9 @@ module Minitest
233
262
  end
234
263
 
235
264
  def self.filter_backtrace bt # :nodoc:
236
- backtrace_filter.filter bt
265
+ result = backtrace_filter.filter bt
266
+ result = bt.dup if result.empty?
267
+ result
237
268
  end
238
269
 
239
270
  ##
@@ -301,7 +332,7 @@ module Minitest
301
332
 
302
333
  def self.run reporter, options = {}
303
334
  filter = options[:filter] || "/./"
304
- filter = Regexp.new $1 if filter =~ %r%/(.*)/%
335
+ filter = Regexp.new $1 if filter.is_a?(String) && filter =~ %r%/(.*)/%
305
336
 
306
337
  filtered_methods = self.runnable_methods.find_all { |m|
307
338
  filter === m || filter === "#{self}##{m}"
@@ -422,7 +453,8 @@ module Minitest
422
453
 
423
454
  ##
424
455
  # Returns a single character string to print based on the result
425
- # of the run. Eg ".", "F", or "E".
456
+ # of the run. One of <tt>"."</tt>, <tt>"F"</tt>,
457
+ # <tt>"E"</tt> or <tt>"S"</tt>.
426
458
 
427
459
  def result_code
428
460
  raise NotImplementedError, "subclass responsibility"
@@ -560,8 +592,10 @@ module Minitest
560
592
  end
561
593
 
562
594
  ##
563
- # Record a result and output the Runnable#result_code. Stores the
564
- # result of the run if the run did not pass.
595
+ # Output and record the result of the test. Call
596
+ # {result#result_code}[rdoc-ref:Runnable#result_code] to get the
597
+ # result character string. Stores the result of the run if the run
598
+ # did not pass.
565
599
 
566
600
  def record result
567
601
  end
@@ -628,18 +662,63 @@ module Minitest
628
662
  #
629
663
  # If you want to create an entirely different type of output (eg,
630
664
  # CI, HTML, etc), this is the place to start.
665
+ #
666
+ # Example:
667
+ #
668
+ # class JenkinsCIReporter < StatisticsReporter
669
+ # def report
670
+ # super # Needed to calculate some statistics
671
+ #
672
+ # print "<testsuite "
673
+ # print "tests='#{count}' "
674
+ # print "failures='#{failures}' "
675
+ # # Remaining XML...
676
+ # end
677
+ # end
631
678
 
632
679
  class StatisticsReporter < Reporter
633
- # :stopdoc:
680
+ ##
681
+ # Total number of assertions.
682
+
634
683
  attr_accessor :assertions
684
+
685
+ ##
686
+ # Total number of test cases.
687
+
635
688
  attr_accessor :count
689
+
690
+ ##
691
+ # An +Array+ of test cases that failed or were skipped.
692
+
636
693
  attr_accessor :results
694
+
695
+ ##
696
+ # Time the test run started. If available, the monotonic clock is
697
+ # used and this is a +Float+, otherwise it's an instance of
698
+ # +Time+.
699
+
637
700
  attr_accessor :start_time
701
+
702
+ ##
703
+ # Test run time. If available, the monotonic clock is used and
704
+ # this is a +Float+, otherwise it's an instance of +Time+.
705
+
638
706
  attr_accessor :total_time
707
+
708
+ ##
709
+ # Total number of tests that failed.
710
+
639
711
  attr_accessor :failures
712
+
713
+ ##
714
+ # Total number of tests that erred.
715
+
640
716
  attr_accessor :errors
717
+
718
+ ##
719
+ # Total number of tests that where skipped.
720
+
641
721
  attr_accessor :skips
642
- # :startdoc:
643
722
 
644
723
  def initialize io = $stdout, options = {} # :nodoc:
645
724
  super
@@ -669,7 +748,10 @@ module Minitest
669
748
  results << result if not result.passed? or result.skipped?
670
749
  end
671
750
 
672
- def report # :nodoc:
751
+ ##
752
+ # Report on the tracked statistics.
753
+
754
+ def report
673
755
  aggregate = results.group_by { |r| r.failure.class }
674
756
  aggregate.default = [] # dumb. group_by should provide this
675
757
 
@@ -726,9 +808,14 @@ module Minitest
726
808
 
727
809
  def aggregated_results io # :nodoc:
728
810
  filtered_results = results.dup
729
- filtered_results.reject!(&:skipped?) unless options[:verbose]
811
+ filtered_results.reject!(&:skipped?) unless
812
+ options[:verbose] or options[:show_skips]
813
+
814
+ skip = options[:skip] || []
730
815
 
731
816
  filtered_results.each_with_index { |result, i|
817
+ next if skip.include? result.result_code
818
+
732
819
  io.puts "\n%3d) %s" % [i+1, result]
733
820
  }
734
821
  io.puts
@@ -736,26 +823,19 @@ module Minitest
736
823
  end
737
824
 
738
825
  def to_s # :nodoc:
739
- aggregated_results(StringIO.new(binary_string)).string
826
+ aggregated_results(StringIO.new(''.b)).string
740
827
  end
741
828
 
742
829
  def summary # :nodoc:
743
830
  extra = ""
744
831
 
745
832
  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"]
833
+ results.any?(&:skipped?) unless
834
+ options[:verbose] or options[:show_skips] or ENV["MT_NO_SKIP_MSG"]
747
835
 
748
836
  "%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
749
837
  [count, assertions, failures, errors, skips, extra]
750
838
  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
839
  end
760
840
 
761
841
  ##
@@ -851,24 +931,21 @@ module Minitest
851
931
  # Assertion wrapping an unexpected error that was raised during a run.
852
932
 
853
933
  class UnexpectedError < Assertion
854
- attr_accessor :exception # :nodoc:
934
+ # TODO: figure out how to use `cause` instead
935
+ attr_accessor :error # :nodoc:
855
936
 
856
- def initialize exception # :nodoc:
937
+ def initialize error # :nodoc:
857
938
  super "Unexpected exception"
858
- self.exception = exception
939
+ self.error = error
859
940
  end
860
941
 
861
942
  def backtrace # :nodoc:
862
- self.exception.backtrace
863
- end
864
-
865
- def error # :nodoc:
866
- self.exception
943
+ self.error.backtrace
867
944
  end
868
945
 
869
946
  def message # :nodoc:
870
947
  bt = Minitest.filter_backtrace(self.backtrace).join "\n "
871
- "#{self.exception.class}: #{self.exception.message}\n #{bt}"
948
+ "#{self.error.class}: #{self.error.message}\n #{bt}"
872
949
  end
873
950
 
874
951
  def result_label # :nodoc:
@@ -904,6 +981,9 @@ module Minitest
904
981
  # Is this running on maglev?
905
982
 
906
983
  def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
984
+ where = Minitest.filter_backtrace(caller).first
985
+ where = where.split(/:in /, 2).first # clean up noise
986
+ warn "DEPRECATED: `maglev?` called from #{where}. This will fail in Minitest 6."
907
987
  "maglev" == platform
908
988
  end
909
989
 
@@ -914,10 +994,20 @@ module Minitest
914
994
  /^ruby/ =~ platform
915
995
  end
916
996
 
997
+ ##
998
+ # Is this running on macOS?
999
+
1000
+ def osx? platform = RUBY_PLATFORM
1001
+ /darwin/ =~ platform
1002
+ end
1003
+
917
1004
  ##
918
1005
  # Is this running on rubinius?
919
1006
 
920
1007
  def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
1008
+ where = Minitest.filter_backtrace(caller).first
1009
+ where = where.split(/:in /, 2).first # clean up noise
1010
+ warn "DEPRECATED: `rubinius?` called from #{where}. This will fail in Minitest 6."
921
1011
  "rbx" == platform
922
1012
  end
923
1013
 
@@ -939,12 +1029,13 @@ module Minitest
939
1029
  MT_RE = %r%lib/minitest% #:nodoc:
940
1030
 
941
1031
  ##
942
- # Filter +bt+ to something useful. Returns the whole thing if $DEBUG.
1032
+ # Filter +bt+ to something useful. Returns the whole thing if
1033
+ # $DEBUG (ruby) or $MT_DEBUG (env).
943
1034
 
944
1035
  def filter bt
945
1036
  return ["No backtrace"] unless bt
946
1037
 
947
- return bt.dup if $DEBUG
1038
+ return bt.dup if $DEBUG || ENV["MT_DEBUG"]
948
1039
 
949
1040
  new_bt = bt.take_while { |line| line !~ MT_RE }
950
1041
  new_bt = bt.select { |line| line !~ MT_RE } if new_bt.empty?
@@ -6,8 +6,27 @@ class Minitest::Test
6
6
  def clean s
7
7
  s.gsub(/^ {6}/, "")
8
8
  end
9
+
10
+ def with_empty_backtrace_filter
11
+ original = Minitest.backtrace_filter
12
+
13
+ obj = Minitest::BacktraceFilter.new
14
+ def obj.filter _bt
15
+ []
16
+ end
17
+
18
+ Minitest::Test.io_lock.synchronize do # try not to trounce in parallel
19
+ begin
20
+ Minitest.backtrace_filter = obj
21
+ yield
22
+ ensure
23
+ Minitest.backtrace_filter = original
24
+ end
25
+ end
26
+ end
9
27
  end
10
28
 
29
+
11
30
  class FakeNamedTest < Minitest::Test
12
31
  @@count = 0
13
32
 
@@ -19,9 +38,20 @@ class FakeNamedTest < Minitest::Test
19
38
  end
20
39
  end
21
40
 
41
+ module MyModule; end
42
+ class AnError < StandardError; include MyModule; end
43
+
22
44
  class MetaMetaMetaTestCase < Minitest::Test
23
45
  attr_accessor :reporter, :output, :tu
24
46
 
47
+ def with_stderr err
48
+ old = $stderr
49
+ $stderr = err
50
+ yield
51
+ ensure
52
+ $stderr = old
53
+ end
54
+
25
55
  def run_tu_with_fresh_reporter flags = %w[--seed 42]
26
56
  options = Minitest.process_args flags
27
57
 
@@ -31,18 +61,20 @@ class MetaMetaMetaTestCase < Minitest::Test
31
61
  reporter << Minitest::SummaryReporter.new(@output, options)
32
62
  reporter << Minitest::ProgressReporter.new(@output, options)
33
63
 
34
- reporter.start
64
+ with_stderr @output do
65
+ reporter.start
35
66
 
36
- yield(reporter) if block_given?
67
+ yield(reporter) if block_given?
37
68
 
38
- @tus ||= [@tu]
39
- @tus.each do |tu|
40
- Minitest::Runnable.runnables.delete tu
69
+ @tus ||= [@tu]
70
+ @tus.each do |tu|
71
+ Minitest::Runnable.runnables.delete tu
41
72
 
42
- tu.run reporter, options
43
- end
73
+ tu.run reporter, options
74
+ end
44
75
 
45
- reporter.report
76
+ reporter.report
77
+ end
46
78
  end
47
79
 
48
80
  def first_reporter
@@ -81,6 +113,8 @@ class MetaMetaMetaTestCase < Minitest::Test
81
113
  output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in')
82
114
  end
83
115
 
116
+ output.gsub!(/( at )[^:]+:\d+/, '\1[FILE:LINE]')
117
+
84
118
  output
85
119
  end
86
120
 
@@ -95,7 +129,7 @@ class MetaMetaMetaTestCase < Minitest::Test
95
129
 
96
130
  def setup
97
131
  super
98
- srand 42
132
+ Minitest.seed = 42
99
133
  Minitest::Test.reset
100
134
  @tu = nil
101
135
  end