minitest 5.20.0 → 5.21.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 667a803a272949e7b05440f91a56155ea3977a5b9d364542801889c5a2fe0ff0
4
- data.tar.gz: 862bf0ff3d24eea4bbe6c7f435ceef19aaa97748f6a87ec3fa51dc218ca79298
3
+ metadata.gz: 93aa935fa793db73b5d06918b074bf4a096277ce370b28de02e8985e9ff9d59c
4
+ data.tar.gz: 02a61902e998e427f82ed68817d8cc37d844de4ad810e306eb4d2e9f7f5157d9
5
5
  SHA512:
6
- metadata.gz: 2284c84ae5f98a3454e9a95417e609ca1a8ef9af8ee8b1fad8f2aca2632fde6a309e266ef1d399d9a7d47337cdcba696500a1b36f1fa7d952615eb390a89e329
7
- data.tar.gz: a76204f74c2caf693a4302065815b871863ae655372d25fc4d41e416b0d4935704c1e1068457b5cda934312e3915ae8a27595ca962c98e544dd45b54cac2aef7
6
+ metadata.gz: 763100b3c3e55372e57bf04cb19f5cd20423df8fed5245436b5bffaac07c2265d98bddb052d924c3257c5d9c1cc9faf2c1cadbf48ffcdf47320c27a3a2e96e2d
7
+ data.tar.gz: 34a53cef30066575612a61bc0d9d991c5a02598b817bc15a61762687258767fa30dcbb9263c0bb850860fc74fc267702382196d936c943f861d3dea91f10160e
checksums.yaml.gz.sig CHANGED
Binary file
data/History.rdoc CHANGED
@@ -1,3 +1,29 @@
1
+ === 5.21.1 / 2024-01-11
2
+
3
+ * 1 bug fix:
4
+
5
+ * Rails' default backtrace filter can't currently work with caller_locations, so reverting back to caller.
6
+
7
+ === 5.21.0 / 2024-01-11
8
+
9
+ * 10 minor enhancements:
10
+
11
+ * Add include_all kw arg to assert_respond_to and refute_respond_to.
12
+ * Added --quiet flag to skip ProgressReporter (prints the dots). Minor speedup.
13
+ * Added Minitest::Compress#compress and added it to UnexpectedError.
14
+ * Added ability to initialize BacktraceFilter w/ custom regexp.
15
+ * Filter failure backtraces using backtrace_filter before calculating location. (thomasmarshall)
16
+ * Make BacktraceFilter#filter compatible with locations (still compares strings).
17
+ * Optimized Assertion#location ~30%.
18
+ * Output relative paths for all failures/errors/backtraces.
19
+ * Refactored location information in assertions, now using locations.
20
+ * Removed thread and mutex_m dependencies. (hsbt, eregon)
21
+
22
+ * 2 bug fixes:
23
+
24
+ * Drop undocumented bt arg in #skip. Dunno why that ever happened, prolly for testing?
25
+ * Fix mock to work with ruby debugger enabled. (keithlayne)
26
+
1
27
  === 5.20.0 / 2023-09-06
2
28
 
3
29
  * 1 minor enhancement:
@@ -9,7 +35,7 @@
9
35
  * 2 minor enhancements:
10
36
 
11
37
  * Add metadata lazy accessor to Runnable / Result. (matteeyah)
12
- * Only load minitest/unit (aka ancient MiniTest compatibility layer) if ENV["MT_COMPAT"]
38
+ * Only load minitest/unit (aka ancient MiniTest compatibility layer) if \ENV[\"MT_COMPAT\"]
13
39
 
14
40
  * 1 bug fix:
15
41
 
@@ -20,7 +46,7 @@
20
46
  * 3 bug fixes:
21
47
 
22
48
  * Avoid extra string allocations when filtering tests. (tenderlove)
23
- * Only mention deprecated ENV['N'] if it is an integer string.
49
+ * Only mention deprecated \ENV[\'N\'] if it is an integer string.
24
50
  * Push up test_order to Minitest::Runnable to fix minitest/hell. (koic)
25
51
 
26
52
  === 5.18.0 / 2023-03-04
@@ -214,7 +240,7 @@
214
240
 
215
241
  * 3 bug fixes:
216
242
 
217
- * Check `option[:filter]` klass before match. Fixes 2.6 warning. (y-yagi)
243
+ * Check \option[:filter] klass before match. Fixes 2.6 warning. (y-yagi)
218
244
  * Fixed Assertions#diff from recalculating if set to nil
219
245
  * Fixed spec section of readme to not use deprecated global expectations. (CheezItMan)
220
246
 
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,81 @@
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
+ [
68
+ " +->> #{n} cycles of #{lines.size} lines:",
69
+ *lines.map { |s| " | #{s}" },
70
+ " +-<<",
71
+ ]
72
+ else
73
+ lines
74
+ end
75
+ }
76
+ end
77
+
78
+ ary
79
+ end
80
+ end
81
+ 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.21.1" # :nodoc:
13
13
 
14
14
  @@installed_at_exit ||= false
15
15
  @@after_run = []
@@ -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
@@ -212,6 +212,10 @@ module Minitest
212
212
  options[:verbose] = true
213
213
  end
214
214
 
215
+ opts.on "-q", "--quiet", "Quiet. Show no progress processing files." do
216
+ options[:quiet] = true
217
+ end
218
+
215
219
  opts.on "--show-skips", "Show skipped at the end of run." do
216
220
  options[:show_skips] = true
217
221
  end
@@ -525,12 +529,14 @@ module Minitest
525
529
  not self.failure
526
530
  end
527
531
 
532
+ BASE_DIR = "#{Dir.pwd}/" # :nodoc:
533
+
528
534
  ##
529
535
  # The location identifier of this test. Depends on a method
530
536
  # existing called class_name.
531
537
 
532
538
  def location
533
- loc = " [#{self.failure.location}]" unless passed? or error?
539
+ loc = " [#{self.failure.location.delete_prefix BASE_DIR}]" unless passed? or error?
534
540
  "#{self.class_name}##{self.name}#{loc}"
535
541
  end
536
542
 
@@ -619,7 +625,10 @@ module Minitest
619
625
  # you want. Go nuts.
620
626
 
621
627
  class AbstractReporter
622
- include Mutex_m
628
+
629
+ def initialize # :nodoc:
630
+ @mutex = Mutex.new
631
+ end
623
632
 
624
633
  ##
625
634
  # Starts reporting on the run.
@@ -655,6 +664,10 @@ module Minitest
655
664
  def passed?
656
665
  true
657
666
  end
667
+
668
+ def synchronize(&block) # :nodoc:
669
+ @mutex.synchronize(&block)
670
+ end
658
671
  end
659
672
 
660
673
  class Reporter < AbstractReporter # :nodoc:
@@ -828,7 +841,7 @@ module Minitest
828
841
  io.puts "# Running:"
829
842
  io.puts
830
843
 
831
- self.sync = io.respond_to? :"sync=" # stupid emacs
844
+ self.sync = io.respond_to? :"sync="
832
845
  self.old_sync, io.sync = io.sync, true if self.sync
833
846
  end
834
847
 
@@ -936,6 +949,8 @@ module Minitest
936
949
  # Represents run failures.
937
950
 
938
951
  class Assertion < Exception
952
+ RE = /in .(?:assert|refute|flunk|pass|fail|raise|must|wont)/ # :nodoc:
953
+
939
954
  def error # :nodoc:
940
955
  self
941
956
  end
@@ -944,12 +959,10 @@ module Minitest
944
959
  # Where was this run before an assertion was raised?
945
960
 
946
961
  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 .*$/, "")
962
+ bt = Minitest.filter_backtrace self.backtrace
963
+ idx = bt.rindex { |s| s.match? RE } || -1 # fall back to first item
964
+
965
+ bt[idx+1].sub(/:in .*$/, "")
953
966
  end
954
967
 
955
968
  def result_code # :nodoc:
@@ -974,11 +987,21 @@ module Minitest
974
987
  # Assertion wrapping an unexpected error that was raised during a run.
975
988
 
976
989
  class UnexpectedError < Assertion
990
+ include Minitest::Compress
991
+
977
992
  # TODO: figure out how to use `cause` instead
978
993
  attr_accessor :error # :nodoc:
979
994
 
980
995
  def initialize error # :nodoc:
981
996
  super "Unexpected exception"
997
+
998
+ if SystemStackError === error then
999
+ bt = error.backtrace
1000
+ new_bt = compress bt
1001
+ error = error.exception "#{bt.size} -> #{new_bt.size}"
1002
+ error.set_backtrace new_bt
1003
+ end
1004
+
982
1005
  self.error = error
983
1006
  end
984
1007
 
@@ -986,8 +1009,11 @@ module Minitest
986
1009
  self.error.backtrace
987
1010
  end
988
1011
 
1012
+ BASE_RE = %r%#{Dir.pwd}/% # :nodoc:
1013
+
989
1014
  def message # :nodoc:
990
- bt = Minitest.filter_backtrace(self.backtrace).join "\n "
1015
+ bt = Minitest.filter_backtrace(self.backtrace).join("\n ")
1016
+ .gsub(BASE_RE, "")
991
1017
  "#{self.error.class}: #{self.error.message}\n #{bt}"
992
1018
  end
993
1019
 
@@ -1071,6 +1097,12 @@ module Minitest
1071
1097
 
1072
1098
  MT_RE = %r%lib/minitest% #:nodoc:
1073
1099
 
1100
+ attr_accessor :regexp
1101
+
1102
+ def initialize regexp = MT_RE
1103
+ self.regexp = regexp
1104
+ end
1105
+
1074
1106
  ##
1075
1107
  # Filter +bt+ to something useful. Returns the whole thing if
1076
1108
  # $DEBUG (ruby) or $MT_DEBUG (env).
@@ -1080,9 +1112,9 @@ module Minitest
1080
1112
 
1081
1113
  return bt.dup if $DEBUG || ENV["MT_DEBUG"]
1082
1114
 
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?
1115
+ new_bt = bt.take_while { |line| line.to_s !~ regexp }
1116
+ new_bt = bt.select { |line| line.to_s !~ regexp } if new_bt.empty?
1117
+ new_bt = bt.dup if new_bt.empty?
1086
1118
 
1087
1119
  new_bt
1088
1120
  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,98 @@ 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
+ skip "NOOOO!!! but I don't care enough right now."
1363
+
1364
+ assert_compress <<~EXP, %w[ a b c b c a b c b c a b c ]
1365
+ +->> 2 cycles of 5 lines:
1366
+ | a
1367
+ | +->> 2 cycles of 2 lines:
1368
+ | | b
1369
+ | | c
1370
+ | +-<<
1371
+ +-<<
1372
+ a
1373
+ b
1374
+ c
1375
+ EXP
1376
+ end
1377
+ end
data.tar.gz.sig CHANGED
Binary file
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.21.1
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-01-12 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.1'
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.1'
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