minitest 5.20.0 → 5.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 667a803a272949e7b05440f91a56155ea3977a5b9d364542801889c5a2fe0ff0
4
- data.tar.gz: 862bf0ff3d24eea4bbe6c7f435ceef19aaa97748f6a87ec3fa51dc218ca79298
3
+ metadata.gz: 36a02c1522b429152689b46166cd66d5325797d0f4efb35c96458932a7917ba8
4
+ data.tar.gz: 699070f4a0c1e0acd2e277c602638373b1d470768a668793e6890aae6e7e49b3
5
5
  SHA512:
6
- metadata.gz: 2284c84ae5f98a3454e9a95417e609ca1a8ef9af8ee8b1fad8f2aca2632fde6a309e266ef1d399d9a7d47337cdcba696500a1b36f1fa7d952615eb390a89e329
7
- data.tar.gz: a76204f74c2caf693a4302065815b871863ae655372d25fc4d41e416b0d4935704c1e1068457b5cda934312e3915ae8a27595ca962c98e544dd45b54cac2aef7
6
+ metadata.gz: e95a14b71c9cd2e27a26c6593d59075357ecc177b8b618e82dd0c5e03ba13f0322f1f0b36c429022450ae98a0fe6039e210dd7a774c0af93ca970d641e6acb16
7
+ data.tar.gz: 7b1bf55227d08443c8270e04d093981fda13aa37f9fd855a3fb74e77ad0c9b8e9c8d391f519f5173151614b3c074e86639a0a9503ff89afd6fad8ddbd44b800f
checksums.yaml.gz.sig CHANGED
Binary file
data/History.rdoc CHANGED
@@ -1,3 +1,46 @@
1
+ === 5.22.0 / 2024-02-05
2
+
3
+ * 1 minor enhancement:
4
+
5
+ * Added "did you mean" output if your --name filter matches nothing. (tenderlove)
6
+
7
+ * 2 bug fixes:
8
+
9
+ * Big cleanup of test filtering. Much prettier / more functional.
10
+ * Fix situation where Assertion#location can't find the location. (pftg)
11
+
12
+ === 5.21.2 / 2024-01-17
13
+
14
+ * 1 bug fix:
15
+
16
+ * Fixed bug in Minitest::Compress#compress formatting w/ nested patterns. Now recurses properly.
17
+
18
+ === 5.21.1 / 2024-01-11
19
+
20
+ * 1 bug fix:
21
+
22
+ * Rails' default backtrace filter can't currently work with caller_locations, so reverting back to caller.
23
+
24
+ === 5.21.0 / 2024-01-11
25
+
26
+ * 10 minor enhancements:
27
+
28
+ * Add include_all kw arg to assert_respond_to and refute_respond_to.
29
+ * Added --quiet flag to skip ProgressReporter (prints the dots). Minor speedup.
30
+ * Added Minitest::Compress#compress and added it to UnexpectedError.
31
+ * Added ability to initialize BacktraceFilter w/ custom regexp.
32
+ * Filter failure backtraces using backtrace_filter before calculating location. (thomasmarshall)
33
+ * Make BacktraceFilter#filter compatible with locations (still compares strings).
34
+ * Optimized Assertion#location ~30%.
35
+ * Output relative paths for all failures/errors/backtraces.
36
+ * Refactored location information in assertions, now using locations.
37
+ * Removed thread and mutex_m dependencies. (hsbt, eregon)
38
+
39
+ * 2 bug fixes:
40
+
41
+ * Drop undocumented bt arg in #skip. Dunno why that ever happened, prolly for testing?
42
+ * Fix mock to work with ruby debugger enabled. (keithlayne)
43
+
1
44
  === 5.20.0 / 2023-09-06
2
45
 
3
46
  * 1 minor enhancement:
@@ -9,7 +52,7 @@
9
52
  * 2 minor enhancements:
10
53
 
11
54
  * Add metadata lazy accessor to Runnable / Result. (matteeyah)
12
- * Only load minitest/unit (aka ancient MiniTest compatibility layer) if ENV["MT_COMPAT"]
55
+ * Only load minitest/unit (aka ancient MiniTest compatibility layer) if \ENV[\"MT_COMPAT\"]
13
56
 
14
57
  * 1 bug fix:
15
58
 
@@ -20,7 +63,7 @@
20
63
  * 3 bug fixes:
21
64
 
22
65
  * Avoid extra string allocations when filtering tests. (tenderlove)
23
- * Only mention deprecated ENV['N'] if it is an integer string.
66
+ * Only mention deprecated \ENV[\'N\'] if it is an integer string.
24
67
  * Push up test_order to Minitest::Runnable to fix minitest/hell. (koic)
25
68
 
26
69
  === 5.18.0 / 2023-03-04
@@ -214,7 +257,7 @@
214
257
 
215
258
  * 3 bug fixes:
216
259
 
217
- * Check `option[:filter]` klass before match. Fixes 2.6 warning. (y-yagi)
260
+ * Check \option[:filter] klass before match. Fixes 2.6 warning. (y-yagi)
218
261
  * Fixed Assertions#diff from recalculating if set to nil
219
262
  * Fixed spec section of readme to not use deprecated global expectations. (CheezItMan)
220
263
 
data/Manifest.txt CHANGED
@@ -9,6 +9,7 @@ lib/minitest.rb
9
9
  lib/minitest/assertions.rb
10
10
  lib/minitest/autorun.rb
11
11
  lib/minitest/benchmark.rb
12
+ lib/minitest/compress.rb
12
13
  lib/minitest/expectations.rb
13
14
  lib/minitest/hell.rb
14
15
  lib/minitest/mock.rb
data/README.rdoc CHANGED
@@ -3,6 +3,7 @@
3
3
  home :: https://github.com/minitest/minitest
4
4
  bugs :: https://github.com/minitest/minitest/issues
5
5
  rdoc :: https://docs.seattlerb.org/minitest
6
+ clog :: https://github.com/minitest/minitest/blob/master/History.rdoc
6
7
  vim :: https://github.com/sunaku/vim-ruby-minitest
7
8
  emacs:: https://github.com/arthurnn/minitest-emacs
8
9
 
@@ -198,6 +198,11 @@ module Minitest
198
198
  assert obj.empty?, msg
199
199
  end
200
200
 
201
+ def _where # :nodoc:
202
+ where = Minitest.filter_backtrace(caller).first
203
+ where = where.split(/:in /, 2).first # clean up noise
204
+ end
205
+
201
206
  E = "" # :nodoc:
202
207
 
203
208
  ##
@@ -221,10 +226,7 @@ module Minitest
221
226
  if Minitest::VERSION =~ /^6/ then
222
227
  refute_nil exp, "Use assert_nil if expecting nil."
223
228
  else
224
- where = Minitest.filter_backtrace(caller).first
225
- where = where.split(/:in /, 2).first # clean up noise
226
-
227
- warn "DEPRECATED: Use assert_nil if expecting nil from #{where}. This will fail in Minitest 6."
229
+ warn "DEPRECATED: Use assert_nil if expecting nil from #{_where}. This will fail in Minitest 6."
228
230
  end
229
231
  end
230
232
 
@@ -449,12 +451,13 @@ module Minitest
449
451
 
450
452
  ##
451
453
  # Fails unless +obj+ responds to +meth+.
454
+ # include_all defaults to false to match Object#respond_to?
452
455
 
453
- def assert_respond_to obj, meth, msg = nil
456
+ def assert_respond_to obj, meth, msg = nil, include_all: false
454
457
  msg = message(msg) {
455
458
  "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
456
459
  }
457
- assert obj.respond_to?(meth), msg
460
+ assert obj.respond_to?(meth, include_all), msg
458
461
  end
459
462
 
460
463
  ##
@@ -474,9 +477,7 @@ module Minitest
474
477
  # Fails unless the call returns a true value
475
478
 
476
479
  def assert_send send_ary, m = nil
477
- where = Minitest.filter_backtrace(caller).first
478
- where = where.split(/:in /, 2).first # clean up noise
479
- warn "DEPRECATED: assert_send. From #{where}"
480
+ warn "DEPRECATED: assert_send. From #{_where}"
480
481
 
481
482
  recv, msg, *args = send_ary
482
483
  m = message(m) {
@@ -807,11 +808,12 @@ module Minitest
807
808
 
808
809
  ##
809
810
  # Fails if +obj+ responds to the message +meth+.
811
+ # include_all defaults to false to match Object#respond_to?
810
812
 
811
- def refute_respond_to obj, meth, msg = nil
813
+ def refute_respond_to obj, meth, msg = nil, include_all: false
812
814
  msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
813
815
 
814
- refute obj.respond_to?(meth), msg
816
+ refute obj.respond_to?(meth, include_all), msg
815
817
  end
816
818
 
817
819
  ##
@@ -830,10 +832,10 @@ module Minitest
830
832
  # gets listed at the end of the run but doesn't cause a failure
831
833
  # exit code.
832
834
 
833
- def skip msg = nil, bt = caller
835
+ def skip msg = nil, _ignored = nil
834
836
  msg ||= "Skipped, no message given"
835
837
  @skip = true
836
- raise Minitest::Skip, msg, bt
838
+ raise Minitest::Skip, msg
837
839
  end
838
840
 
839
841
  ##
@@ -0,0 +1,94 @@
1
+ module Minitest
2
+ ##
3
+ # Compresses backtraces.
4
+
5
+ module Compress
6
+
7
+ ##
8
+ # Takes a backtrace (array of strings) and compresses repeating
9
+ # cycles in it to make it more readable.
10
+
11
+ def compress orig
12
+ ary = orig
13
+
14
+ eswo = ->(ary, n, off) { # each_slice_with_offset
15
+ if off.zero? then
16
+ ary.each_slice n
17
+ else
18
+ # [ ...off... [...n...] [...n...] ... ]
19
+ front, back = ary.take(off), ary.drop(off)
20
+ [front].chain back.each_slice n
21
+ end
22
+ }
23
+
24
+ 3.times do # maybe don't use loop do here?
25
+ index = ary # [ a b c b c b c d ]
26
+ .size
27
+ .times # 0...size
28
+ .group_by { |i| ary[i] } # { a: [0] b: [1 3 5], c: [2 4 6], d: [7] }
29
+
30
+ order = index
31
+ .reject { |k, v| v.size == 1 } # { b: [1 3 5], c: [2 4 6] }
32
+ .sort_by { |k, ary| ### sort by max dist + min offset
33
+ d = ary.each_cons(2).sum { |a, b| b-a }
34
+ [-d, ary.first]
35
+ } # b: [1 3 5] c: [2 4 6]
36
+
37
+ ranges = order
38
+ .map { |k, ary| # [[1..2 3..4] [2..3 4..5]]
39
+ ary
40
+ .each_cons(2)
41
+ .map { |a, b| a..b-1 }
42
+ }
43
+
44
+ big_ranges = ranges
45
+ .flat_map { |a| # [1..2 3..4 2..3 4..5]
46
+ a.sort_by { |r| [-r.size, r.first] }.first 5
47
+ }
48
+ .first(100)
49
+
50
+ culprits = big_ranges
51
+ .map { |r|
52
+ eswo[ary, r.size, r.begin] # [o1 s1 s1 s2 s2]
53
+ .chunk_while { |a,b| a == b } # [[o1] [s1 s1] [s2 s2]]
54
+ .map { |a| [a.size, a.first] } # [[1 o1] [2 s1] [2 s2]]
55
+ }
56
+ .select { |chunks|
57
+ chunks.any? { |a| a.first > 1 } # compressed anything?
58
+ }
59
+
60
+ min = culprits
61
+ .min_by { |a| a.flatten.size } # most compressed
62
+
63
+ break unless min
64
+
65
+ ary = min.flat_map { |(n, lines)|
66
+ if n > 1 then
67
+ [[n, compress(lines)]] # [o1 [2 s1] [2 s2]]
68
+ else
69
+ lines
70
+ end
71
+ }
72
+ end
73
+
74
+ format = ->(lines) {
75
+ lines.flat_map { |line|
76
+ case line
77
+ when Array then
78
+ n, lines = line
79
+ lines = format[lines]
80
+ [
81
+ " +->> #{n} cycles of #{lines.size} lines:",
82
+ *lines.map { |s| " | #{s}" },
83
+ " +-<<",
84
+ ]
85
+ else
86
+ line
87
+ end
88
+ }
89
+ }
90
+
91
+ format[ary]
92
+ end
93
+ end
94
+ end
data/lib/minitest/mock.rb CHANGED
@@ -10,7 +10,7 @@ module Minitest # :nodoc:
10
10
  class Mock
11
11
  alias :__respond_to? :respond_to?
12
12
 
13
- overridden_methods = %w[
13
+ overridden_methods = %i[
14
14
  ===
15
15
  class
16
16
  inspect
@@ -23,8 +23,10 @@ module Minitest # :nodoc:
23
23
  to_s
24
24
  ]
25
25
 
26
+ overridden_methods << :singleton_method_added if defined?(::DEBUGGER__)
27
+
26
28
  instance_methods.each do |m|
27
- undef_method m unless overridden_methods.include?(m.to_s) || m =~ /^__/
29
+ undef_method m unless overridden_methods.include?(m) || m =~ /^__/
28
30
  end
29
31
 
30
32
  overridden_methods.map(&:to_sym).each do |method_id|
@@ -288,7 +288,6 @@ end
288
288
 
289
289
  class Integer # :nodoc:
290
290
  def threads_do(jobs) # :nodoc:
291
- require "thread"
292
291
  q = Work.new jobs
293
292
 
294
293
  self.times.map {
data/lib/minitest.rb CHANGED
@@ -1,15 +1,15 @@
1
1
  require "optparse"
2
- require "thread"
3
- require "mutex_m"
4
- require "minitest/parallel"
5
2
  require "stringio"
6
3
  require "etc"
7
4
 
5
+ require_relative "minitest/parallel"
6
+ require_relative "minitest/compress"
7
+
8
8
  ##
9
9
  # :include: README.rdoc
10
10
 
11
11
  module Minitest
12
- VERSION = "5.20.0" # :nodoc:
12
+ VERSION = "5.22.0" # :nodoc:
13
13
 
14
14
  @@installed_at_exit ||= false
15
15
  @@after_run = []
@@ -134,7 +134,7 @@ module Minitest
134
134
  # Minitest.run(args)
135
135
  # Minitest.__run(reporter, options)
136
136
  # Runnable.runnables.each
137
- # runnable.run(reporter, options)
137
+ # runnable_klass.run(reporter, options)
138
138
  # self.runnable_methods.each
139
139
  # self.run_one_method(self, runnable_method, reporter)
140
140
  # Minitest.run_one_method(klass, runnable_method)
@@ -150,7 +150,7 @@ module Minitest
150
150
 
151
151
  reporter = CompositeReporter.new
152
152
  reporter << SummaryReporter.new(options[:io], options)
153
- reporter << ProgressReporter.new(options[:io], options)
153
+ reporter << ProgressReporter.new(options[:io], options) unless options[:quiet]
154
154
 
155
155
  self.reporter = reporter # this makes it available to plugins
156
156
  self.init_plugins options
@@ -164,11 +164,33 @@ module Minitest
164
164
  warn "Interrupted. Exiting..."
165
165
  end
166
166
  self.parallel_executor.shutdown
167
+
168
+ # might have been removed/replaced during init_plugins:
169
+ summary = reporter.reporters.grep(SummaryReporter).first
170
+ return empty_run! options if summary && summary.count == 0
171
+
167
172
  reporter.report
168
173
 
169
174
  reporter.passed?
170
175
  end
171
176
 
177
+ def self.empty_run! options # :nodoc:
178
+ filter = options[:filter]
179
+
180
+ warn "Nothing ran for filter: %s" % [filter]
181
+
182
+ require "did_you_mean" # soft dependency, punt if it doesn't load
183
+
184
+ ms = Runnable.runnables.flat_map(&:runnable_methods)
185
+ cs = DidYouMean::SpellChecker.new(dictionary: ms).correct filter
186
+
187
+ warn DidYouMean::Formatter.message_for cs unless cs.empty?
188
+ rescue LoadError
189
+ # do nothing
190
+ ensure
191
+ false
192
+ end
193
+
172
194
  ##
173
195
  # Internal run method. Responsible for telling all Runnable
174
196
  # sub-classes to run.
@@ -212,6 +234,10 @@ module Minitest
212
234
  options[:verbose] = true
213
235
  end
214
236
 
237
+ opts.on "-q", "--quiet", "Quiet. Show no progress processing files." do
238
+ options[:quiet] = true
239
+ end
240
+
215
241
  opts.on "--show-skips", "Show skipped at the end of run." do
216
242
  options[:show_skips] = true
217
243
  end
@@ -334,25 +360,15 @@ module Minitest
334
360
  # reporter to record.
335
361
 
336
362
  def self.run reporter, options = {}
337
- filtered_methods = if options[:filter]
338
- filter = options[:filter]
339
- filter = Regexp.new $1 if filter.is_a?(String) && filter =~ %r%/(.*)/%
340
-
341
- self.runnable_methods.find_all { |m|
342
- filter === m || filter === "#{self}##{m}"
343
- }
344
- else
345
- self.runnable_methods
346
- end
363
+ pos = options[:filter]
364
+ neg = options[:exclude]
347
365
 
348
- if options[:exclude]
349
- exclude = options[:exclude]
350
- exclude = Regexp.new $1 if exclude =~ %r%/(.*)/%
366
+ pos = Regexp.new $1 if pos.is_a?(String) && pos =~ %r%/(.*)/%
367
+ neg = Regexp.new $1 if neg.is_a?(String) && neg =~ %r%/(.*)/%
351
368
 
352
- filtered_methods.delete_if { |m|
353
- exclude === m || exclude === "#{self}##{m}"
354
- }
355
- end
369
+ filtered_methods = self.runnable_methods
370
+ .select { |m| !pos || pos === m || pos === "#{self}##{m}" }
371
+ .reject { |m| neg && (neg === m || neg === "#{self}##{m}") }
356
372
 
357
373
  return if filtered_methods.empty?
358
374
 
@@ -525,12 +541,14 @@ module Minitest
525
541
  not self.failure
526
542
  end
527
543
 
544
+ BASE_DIR = "#{Dir.pwd}/" # :nodoc:
545
+
528
546
  ##
529
547
  # The location identifier of this test. Depends on a method
530
548
  # existing called class_name.
531
549
 
532
550
  def location
533
- loc = " [#{self.failure.location}]" unless passed? or error?
551
+ loc = " [#{self.failure.location.delete_prefix BASE_DIR}]" unless passed? or error?
534
552
  "#{self.class_name}##{self.name}#{loc}"
535
553
  end
536
554
 
@@ -619,7 +637,10 @@ module Minitest
619
637
  # you want. Go nuts.
620
638
 
621
639
  class AbstractReporter
622
- include Mutex_m
640
+
641
+ def initialize # :nodoc:
642
+ @mutex = Mutex.new
643
+ end
623
644
 
624
645
  ##
625
646
  # Starts reporting on the run.
@@ -655,6 +676,10 @@ module Minitest
655
676
  def passed?
656
677
  true
657
678
  end
679
+
680
+ def synchronize(&block) # :nodoc:
681
+ @mutex.synchronize(&block)
682
+ end
658
683
  end
659
684
 
660
685
  class Reporter < AbstractReporter # :nodoc:
@@ -828,7 +853,7 @@ module Minitest
828
853
  io.puts "# Running:"
829
854
  io.puts
830
855
 
831
- self.sync = io.respond_to? :"sync=" # stupid emacs
856
+ self.sync = io.respond_to? :"sync="
832
857
  self.old_sync, io.sync = io.sync, true if self.sync
833
858
  end
834
859
 
@@ -936,6 +961,8 @@ module Minitest
936
961
  # Represents run failures.
937
962
 
938
963
  class Assertion < Exception
964
+ RE = /in .(?:assert|refute|flunk|pass|fail|raise|must|wont)/ # :nodoc:
965
+
939
966
  def error # :nodoc:
940
967
  self
941
968
  end
@@ -944,12 +971,11 @@ module Minitest
944
971
  # Where was this run before an assertion was raised?
945
972
 
946
973
  def location
947
- last_before_assertion = ""
948
- self.backtrace.reverse_each do |s|
949
- break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
950
- last_before_assertion = s
951
- end
952
- last_before_assertion.sub(/:in .*$/, "")
974
+ bt = Minitest.filter_backtrace self.backtrace
975
+ idx = bt.rindex { |s| s.match? RE } || -1 # fall back to first item
976
+ loc = bt[idx+1] || bt.last || "unknown:-1"
977
+
978
+ loc.sub(/:in .*$/, "")
953
979
  end
954
980
 
955
981
  def result_code # :nodoc:
@@ -974,11 +1000,21 @@ module Minitest
974
1000
  # Assertion wrapping an unexpected error that was raised during a run.
975
1001
 
976
1002
  class UnexpectedError < Assertion
1003
+ include Minitest::Compress
1004
+
977
1005
  # TODO: figure out how to use `cause` instead
978
1006
  attr_accessor :error # :nodoc:
979
1007
 
980
1008
  def initialize error # :nodoc:
981
1009
  super "Unexpected exception"
1010
+
1011
+ if SystemStackError === error then
1012
+ bt = error.backtrace
1013
+ new_bt = compress bt
1014
+ error = error.exception "#{bt.size} -> #{new_bt.size}"
1015
+ error.set_backtrace new_bt
1016
+ end
1017
+
982
1018
  self.error = error
983
1019
  end
984
1020
 
@@ -986,8 +1022,11 @@ module Minitest
986
1022
  self.error.backtrace
987
1023
  end
988
1024
 
1025
+ BASE_RE = %r%#{Dir.pwd}/% # :nodoc:
1026
+
989
1027
  def message # :nodoc:
990
- bt = Minitest.filter_backtrace(self.backtrace).join "\n "
1028
+ bt = Minitest.filter_backtrace(self.backtrace).join("\n ")
1029
+ .gsub(BASE_RE, "")
991
1030
  "#{self.error.class}: #{self.error.message}\n #{bt}"
992
1031
  end
993
1032
 
@@ -1071,6 +1110,12 @@ module Minitest
1071
1110
 
1072
1111
  MT_RE = %r%lib/minitest% #:nodoc:
1073
1112
 
1113
+ attr_accessor :regexp
1114
+
1115
+ def initialize regexp = MT_RE
1116
+ self.regexp = regexp
1117
+ end
1118
+
1074
1119
  ##
1075
1120
  # Filter +bt+ to something useful. Returns the whole thing if
1076
1121
  # $DEBUG (ruby) or $MT_DEBUG (env).
@@ -1080,9 +1125,9 @@ module Minitest
1080
1125
 
1081
1126
  return bt.dup if $DEBUG || ENV["MT_DEBUG"]
1082
1127
 
1083
- new_bt = bt.take_while { |line| line !~ MT_RE }
1084
- new_bt = bt.select { |line| line !~ MT_RE } if new_bt.empty?
1085
- new_bt = bt.dup if new_bt.empty?
1128
+ new_bt = bt.take_while { |line| line.to_s !~ regexp }
1129
+ new_bt = bt.select { |line| line.to_s !~ regexp } if new_bt.empty?
1130
+ new_bt = bt.dup if new_bt.empty?
1086
1131
 
1087
1132
  new_bt
1088
1133
  end
@@ -8,16 +8,17 @@ class Minitest::Test
8
8
  end
9
9
 
10
10
  def with_empty_backtrace_filter
11
- original = Minitest.backtrace_filter
12
-
13
- obj = Minitest::BacktraceFilter.new
14
- def obj.filter _bt
15
- []
11
+ with_backtrace_filter Minitest::BacktraceFilter.new %r%.% do
12
+ yield
16
13
  end
14
+ end
15
+
16
+ def with_backtrace_filter filter
17
+ original = Minitest.backtrace_filter
17
18
 
18
19
  Minitest::Test.io_lock.synchronize do # try not to trounce in parallel
19
20
  begin
20
- Minitest.backtrace_filter = obj
21
+ Minitest.backtrace_filter = filter
21
22
  yield
22
23
  ensure
23
24
  Minitest.backtrace_filter = original
@@ -105,15 +106,17 @@ class MetaMetaMetaTestCase < Minitest::Test
105
106
  output.gsub!(/0x[A-Fa-f0-9]+/, "0xXXX")
106
107
  output.gsub!(/ +$/, "")
107
108
 
109
+ file = ->(s) { s.start_with?("/") ? "FULLFILE" : "FILE" }
110
+
108
111
  if windows? then
109
112
  output.gsub!(/\[(?:[A-Za-z]:)?[^\]:]+:\d+\]/, "[FILE:LINE]")
110
113
  output.gsub!(/^(\s+)(?:[A-Za-z]:)?[^:]+:\d+:in/, '\1FILE:LINE:in')
111
114
  else
112
- output.gsub!(/\[[^\]:]+:\d+\]/, "[FILE:LINE]")
113
- output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in')
115
+ output.gsub!(/\[([^\]:]+):\d+\]/) { "[#{file[$1]}:LINE]" }
116
+ output.gsub!(/^(\s+)([^:]+):\d+:in/) { "#{$1}#{file[$2]}:LINE:in" }
114
117
  end
115
118
 
116
- output.gsub!(/( at )[^:]+:\d+/, '\1[FILE:LINE]')
119
+ output.gsub!(/( at )[^:]+:\d+/) { "#{$1}[#{file[$2]}:LINE]" } # eval?
117
120
 
118
121
  output
119
122
  end
@@ -936,6 +936,16 @@ class TestMinitestAssertions < Minitest::Test
936
936
  end
937
937
  end
938
938
 
939
+ def test_assert_respond_to__include_all
940
+ @tc.assert_respond_to @tc, :exit, include_all: true
941
+ end
942
+
943
+ def test_assert_respond_to__include_all_triggered
944
+ assert_triggered(/Expected .+::DummyTest. to respond to #exit\?/) do
945
+ @tc.assert_respond_to @tc, :exit?, include_all: true
946
+ end
947
+ end
948
+
939
949
  def test_assert_same
940
950
  @assertion_count = 3
941
951
 
@@ -1153,18 +1163,14 @@ class TestMinitestAssertions < Minitest::Test
1153
1163
  def test_class_asserts_match_refutes
1154
1164
  @assertion_count = 0
1155
1165
 
1156
- methods = Minitest::Assertions.public_instance_methods
1157
- methods.map!(&:to_s) if Symbol === methods.first
1166
+ methods = Minitest::Assertions.public_instance_methods.map(&:to_s)
1158
1167
 
1159
1168
  # These don't have corresponding refutes _on purpose_. They're
1160
1169
  # useless and will never be added, so don't bother.
1161
1170
  ignores = %w[assert_output assert_raises assert_send
1162
1171
  assert_silent assert_throws assert_mock]
1163
1172
 
1164
- # These are test/unit methods. I'm not actually sure why they're still here
1165
- ignores += %w[assert_no_match assert_not_equal assert_not_nil
1166
- assert_not_same assert_nothing_raised
1167
- assert_nothing_thrown assert_raise]
1173
+ ignores += %w[assert_allocations] # for minitest-gcstats
1168
1174
 
1169
1175
  asserts = methods.grep(/^assert/).sort - ignores
1170
1176
  refutes = methods.grep(/^refute/).sort - ignores
@@ -1444,6 +1450,16 @@ class TestMinitestAssertions < Minitest::Test
1444
1450
  end
1445
1451
  end
1446
1452
 
1453
+ def test_refute_respond_to__include_all
1454
+ @tc.refute_respond_to "blah", :missing, include_all: true
1455
+ end
1456
+
1457
+ def test_refute_respond_to__include_all_triggered
1458
+ assert_triggered(/Expected .*DummyTest.* to not respond to exit./) do
1459
+ @tc.refute_respond_to @tc, :exit, include_all: true
1460
+ end
1461
+ end
1462
+
1447
1463
  def test_refute_same
1448
1464
  @tc.refute_same 1, 2
1449
1465
  end
@@ -48,6 +48,25 @@ class TestMinitestReporter < MetaMetaMetaTestCase
48
48
  @et
49
49
  end
50
50
 
51
+ def system_stack_error_test
52
+ unless defined? @sse then
53
+
54
+ ex = SystemStackError.new
55
+
56
+ pre = ("a".."c").to_a
57
+ mid = ("aa".."ad").to_a * 67
58
+ post = ("d".."f").to_a
59
+ ary = pre + mid + post
60
+
61
+ ex.set_backtrace ary
62
+
63
+ @sse = Minitest::Test.new(:woot)
64
+ @sse.failures << Minitest::UnexpectedError.new(ex)
65
+ @sse = Minitest::Result.from @sse
66
+ end
67
+ @sse
68
+ end
69
+
51
70
  def fail_test
52
71
  unless defined? @ft then
53
72
  @ft = Minitest::Test.new(:woot)
@@ -314,6 +333,42 @@ class TestMinitestReporter < MetaMetaMetaTestCase
314
333
  assert_equal exp, normalize_output(io.string)
315
334
  end
316
335
 
336
+ def test_report_error__sse
337
+ r.start
338
+ r.record system_stack_error_test
339
+ r.report
340
+
341
+ exp = clean <<-EOM
342
+ Run options:
343
+
344
+ # Running:
345
+
346
+ E
347
+
348
+ Finished in 0.00
349
+
350
+ 1) Error:
351
+ Minitest::Test#woot:
352
+ SystemStackError: 274 -> 12
353
+ a
354
+ b
355
+ c
356
+ +->> 67 cycles of 4 lines:
357
+ | aa
358
+ | ab
359
+ | ac
360
+ | ad
361
+ +-<<
362
+ d
363
+ e
364
+ f
365
+
366
+ 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
367
+ EOM
368
+
369
+ assert_equal exp, normalize_output(io.string)
370
+ end
371
+
317
372
  def test_report_skipped
318
373
  r.start
319
374
  r.record skip_test
@@ -338,4 +393,48 @@ class TestMinitestReporter < MetaMetaMetaTestCase
338
393
 
339
394
  assert_equal exp, normalize_output(io.string)
340
395
  end
396
+
397
+ def test_report_failure_uses_backtrace_filter
398
+ filter = Minitest::BacktraceFilter.new
399
+ def filter.filter _bt
400
+ ["foo.rb:123:in `foo'"]
401
+ end
402
+
403
+ with_backtrace_filter filter do
404
+ r.start
405
+ r.record fail_test
406
+ r.report
407
+ end
408
+
409
+ exp = "Minitest::Test#woot [foo.rb:123]"
410
+
411
+ assert_includes io.string, exp
412
+ end
413
+
414
+ def test_report_failure_uses_backtrace_filter_complex_sorbet
415
+ backtrace = <<~EOBT
416
+ /Users/user/.gem/ruby/3.2.2/gems/minitest-5.20.0/lib/minitest/assertions.rb:183:in `assert'
417
+ example_test.rb:9:in `assert_false'
418
+ /Users/user/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.11068/lib/types/private/methods/call_validation.rb:256:in `bind_call'
419
+ /Users/user/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.11068/lib/types/private/methods/call_validation.rb:256:in `validate_call'
420
+ /Users/user/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.11068/lib/types/private/methods/_methods.rb:275:in `block in _on_method_added'
421
+ example_test.rb:25:in `test_something'
422
+ /Users/user/.gem/ruby/3.2.2/gems/minitest-5.20.0/lib/minitest/test.rb:94:in `block (3 levels) in run'
423
+ /Users/user/.gem/ruby/3.2.2/gems/minitest-5.20.0/lib/minitest/test.rb:191:in `capture_exceptions'
424
+ /Users/user/.gem/ruby/3.2.2/gems/minitest-5.20.0/lib/minitest/test.rb:89:in `block (2 levels) in run'
425
+ ... so many lines ...
426
+ EOBT
427
+
428
+ filter = Minitest::BacktraceFilter.new %r%lib/minitest|gems/sorbet%
429
+
430
+ with_backtrace_filter filter do
431
+ begin
432
+ assert_equal 1, 2
433
+ rescue Minitest::Assertion => e
434
+ e.set_backtrace backtrace.lines.map(&:chomp)
435
+
436
+ assert_match "example_test.rb:25", e.location
437
+ end
438
+ end
439
+ end
341
440
  end
@@ -1280,3 +1280,96 @@ class TestMinitestUnitRecording < MetaMetaMetaTestCase
1280
1280
  end
1281
1281
  end
1282
1282
  end
1283
+
1284
+ class TestUnexpectedError < Minitest::Test
1285
+ def assert_compress exp, input
1286
+ e = Minitest::UnexpectedError.new RuntimeError.new
1287
+
1288
+ exp = exp.lines.map(&:chomp) if String === exp
1289
+ act = e.compress input
1290
+
1291
+ assert_equal exp, act
1292
+ end
1293
+
1294
+ ACT1 = %w[ a b c b c b c b c d ]
1295
+
1296
+ def test_normal
1297
+ assert_compress <<~EXP, %w[ a b c b c b c b c d ]
1298
+ a
1299
+ +->> 4 cycles of 2 lines:
1300
+ | b
1301
+ | c
1302
+ +-<<
1303
+ d
1304
+ EXP
1305
+ end
1306
+
1307
+ def test_normal2
1308
+ assert_compress <<~EXP, %w[ a b c b c b c b c ]
1309
+ a
1310
+ +->> 4 cycles of 2 lines:
1311
+ | b
1312
+ | c
1313
+ +-<<
1314
+ EXP
1315
+ end
1316
+
1317
+ def test_longer_c_than_b
1318
+ # the extra c in the front makes the overall length longer sorting it first
1319
+ assert_compress <<~EXP, %w[ c a b c b c b c b c b d ]
1320
+ c
1321
+ a
1322
+ b
1323
+ +->> 4 cycles of 2 lines:
1324
+ | c
1325
+ | b
1326
+ +-<<
1327
+ d
1328
+ EXP
1329
+ end
1330
+
1331
+ def test_1_line_cycles
1332
+ assert_compress <<~EXP, %w[ c a b c b c b c b c b b b d ]
1333
+ c
1334
+ a
1335
+ +->> 4 cycles of 2 lines:
1336
+ | b
1337
+ | c
1338
+ +-<<
1339
+ +->> 3 cycles of 1 lines:
1340
+ | b
1341
+ +-<<
1342
+ d
1343
+ EXP
1344
+ end
1345
+
1346
+ def test_sanity3
1347
+ pre = ("aa".."am").to_a
1348
+ mid = ("a".."z").to_a * 67
1349
+ post = ("aa".."am").to_a
1350
+ ary = pre + mid + post
1351
+
1352
+ exp = pre +
1353
+ [" +->> 67 cycles of 26 lines:"] +
1354
+ ("a".."z").map { |s| " | #{s}" } +
1355
+ [" +-<<"] +
1356
+ post
1357
+
1358
+ assert_compress exp, ary
1359
+ end
1360
+
1361
+ def test_absurd_patterns
1362
+ assert_compress <<~EXP, %w[ a b c b c a b c b c a b c ]
1363
+ +->> 2 cycles of 5 lines:
1364
+ | a
1365
+ | +->> 2 cycles of 2 lines:
1366
+ | | b
1367
+ | | c
1368
+ | +-<<
1369
+ +-<<
1370
+ a
1371
+ b
1372
+ c
1373
+ EXP
1374
+ end
1375
+ end
data.tar.gz.sig CHANGED
@@ -1,4 +1,4 @@
1
- ^�bG�@�����Ąw��nr��:@�
2
- ���Q���%�`d�[M�S7#�N�Ǟ,sVn=5��ݕ��0+E$��0���K�Kn80br�
3
- �ʜ�}�� ���mO��i
4
- ��=
1
+ gD6P���T!=�q/{�_]r�����2Z¬��ݒـY'8�����Ѵ�D���)��X\��]nZ�x2O��U��� et��Z��R
2
+
3
+ s�v0j
4
+ `�c��#!���%O�D<قF�g�g�
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitest
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.20.0
4
+ version: 5.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Davis
@@ -10,9 +10,9 @@ bindir: bin
10
10
  cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
- MIIDPjCCAiagAwIBAgIBBzANBgkqhkiG9w0BAQsFADBFMRMwEQYDVQQDDApyeWFu
13
+ MIIDPjCCAiagAwIBAgIBCDANBgkqhkiG9w0BAQsFADBFMRMwEQYDVQQDDApyeWFu
14
14
  ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
15
- GRYDY29tMB4XDTIzMDEwMTA3NTExN1oXDTI0MDEwMTA3NTExN1owRTETMBEGA1UE
15
+ GRYDY29tMB4XDTI0MDEwMjIxMjEyM1oXDTI1MDEwMTIxMjEyM1owRTETMBEGA1UE
16
16
  AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
17
17
  JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
18
18
  b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
@@ -22,14 +22,14 @@ cert_chain:
22
22
  qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
23
23
  gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
24
24
  HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBCwUAA4IB
25
- AQAkg3y+PBnBAPWdxxITm5sPHqdWQgSyCpRA20o4LTuWr8BWhSXBkfQNa7cY6fOn
26
- xyM34VPzBFbExv6XOGDfOMFBVaYTHuN9peC/5/umL7kLl+nflXzL2QA7K6LYj5Bg
27
- sM574Onr0dZDM6Vn69bzQ7rBIFDfK/OhlPzqKZad4nsdcsVH8ODCiT+ATMIZyz5K
28
- WCnNtqlyiWXI8tdTpahDgcUwfcN/oN7v4K8iU5IbLJX6HQ5DKgmKjfb6XyMth16k
29
- ROfWo9Uyp8ba/j9eVG14KkYRaLydAY1MNQk2yd3R5CGfeOpD1kttxjoypoUJ2dOG
30
- nsNBRuQJ1UfiCG97a6DNm+Fr
25
+ AQCygvpmncmkiSs9r/Kceo4bBPDszhTv6iBi4LwMReqnFrpNLMOWJw7xi8x+3eL2
26
+ XS09ZPNOt2zm70KmFouBMgOysnDY4k2dE8uF6B8JbZOO8QfalW+CoNBliefOTcn2
27
+ bg5IOP7UoGM5lC174/cbDJrJnRG9bzig5FAP0mvsgA8zgTRXQzIUAZEo92D5K7p4
28
+ B4/O998ho6BSOgYBI9Yk1ttdCtti6Y+8N9+fZESsjtWMykA+WXWeGUScHqiU+gH8
29
+ S7043fq9EbQdBr2AXdj92+CDwuTfHI6/Hj5FVBDULufrJaan4xUgL70Hvc6pTTeW
30
+ deKfBjgVAq7EYHu1AczzlUly
31
31
  -----END CERTIFICATE-----
32
- date: 2023-09-06 00:00:00.000000000 Z
32
+ date: 2024-02-05 00:00:00.000000000 Z
33
33
  dependencies:
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: rdoc
@@ -57,14 +57,14 @@ dependencies:
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '4.0'
60
+ version: '4.2'
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '4.0'
67
+ version: '4.2'
68
68
  description: |-
69
69
  minitest provides a complete suite of testing facilities supporting
70
70
  TDD, BDD, mocking, and benchmarking.
@@ -139,6 +139,7 @@ files:
139
139
  - lib/minitest/assertions.rb
140
140
  - lib/minitest/autorun.rb
141
141
  - lib/minitest/benchmark.rb
142
+ - lib/minitest/compress.rb
142
143
  - lib/minitest/expectations.rb
143
144
  - lib/minitest/hell.rb
144
145
  - lib/minitest/mock.rb
@@ -163,6 +164,7 @@ licenses:
163
164
  metadata:
164
165
  homepage_uri: https://github.com/minitest/minitest
165
166
  bug_tracker_uri: https://github.com/minitest/minitest/issues
167
+ changelog_uri: https://github.com/minitest/minitest/blob/master/History.rdoc
166
168
  post_install_message:
167
169
  rdoc_options:
168
170
  - "--main"
@@ -183,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
185
  - !ruby/object:Gem::Version
184
186
  version: '0'
185
187
  requirements: []
186
- rubygems_version: 3.4.10
188
+ rubygems_version: 3.5.3
187
189
  signing_key:
188
190
  specification_version: 4
189
191
  summary: minitest provides a complete suite of testing facilities supporting TDD,
metadata.gz.sig CHANGED
Binary file