minitest 5.16.3 → 5.25.1
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.rdoc +176 -1
- data/Manifest.txt +3 -0
- data/README.rdoc +26 -25
- data/Rakefile +7 -0
- data/lib/hoe/minitest.rb +2 -1
- data/lib/minitest/assertions.rb +126 -79
- data/lib/minitest/autorun.rb +0 -7
- data/lib/minitest/benchmark.rb +6 -9
- data/lib/minitest/compress.rb +94 -0
- data/lib/minitest/error_on_warning.rb +11 -0
- data/lib/minitest/expectations.rb +18 -0
- data/lib/minitest/manual_plugins.rb +16 -0
- data/lib/minitest/mock.rb +23 -17
- data/lib/minitest/parallel.rb +5 -5
- data/lib/minitest/pride_plugin.rb +16 -23
- data/lib/minitest/spec.rb +10 -4
- data/lib/minitest/test.rb +22 -37
- data/lib/minitest/test_task.rb +24 -22
- data/lib/minitest.rb +296 -148
- data/test/minitest/metametameta.rb +32 -18
- data/test/minitest/test_minitest_assertions.rb +269 -140
- data/test/minitest/test_minitest_benchmark.rb +1 -1
- data/test/minitest/test_minitest_mock.rb +89 -77
- data/test/minitest/test_minitest_reporter.rb +139 -15
- data/test/minitest/test_minitest_spec.rb +130 -55
- data/test/minitest/test_minitest_test.rb +200 -116
- data/test/minitest/test_minitest_test_task.rb +18 -7
- data.tar.gz.sig +0 -0
- metadata +20 -16
- metadata.gz.sig +0 -0
data/lib/minitest/assertions.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
require "rbconfig"
|
4
2
|
require "tempfile"
|
5
3
|
require "stringio"
|
@@ -29,12 +27,12 @@ module Minitest
|
|
29
27
|
def self.diff
|
30
28
|
return @diff if defined? @diff
|
31
29
|
|
32
|
-
@diff = if (RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
33
|
-
system
|
30
|
+
@diff = if (RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ and
|
31
|
+
system "diff.exe", __FILE__, __FILE__) then
|
34
32
|
"diff.exe -u"
|
35
|
-
elsif system
|
33
|
+
elsif system "gdiff", __FILE__, __FILE__ then
|
36
34
|
"gdiff -u" # solaris and kin suck
|
37
|
-
elsif system
|
35
|
+
elsif system "diff", __FILE__, __FILE__ then
|
38
36
|
"diff -u"
|
39
37
|
else
|
40
38
|
nil
|
@@ -59,16 +57,16 @@ module Minitest
|
|
59
57
|
def diff exp, act
|
60
58
|
result = nil
|
61
59
|
|
62
|
-
expect, butwas = things_to_diff
|
60
|
+
expect, butwas = things_to_diff exp, act
|
63
61
|
|
64
62
|
return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless
|
65
63
|
expect
|
66
64
|
|
67
|
-
Tempfile.open
|
65
|
+
Tempfile.open "expect" do |a|
|
68
66
|
a.puts expect
|
69
67
|
a.flush
|
70
68
|
|
71
|
-
Tempfile.open
|
69
|
+
Tempfile.open "butwas" do |b|
|
72
70
|
b.puts butwas
|
73
71
|
b.flush
|
74
72
|
|
@@ -79,10 +77,10 @@ module Minitest
|
|
79
77
|
if result.empty? then
|
80
78
|
klass = exp.class
|
81
79
|
result = [
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
"No visible difference in the #{klass}#inspect output.\n",
|
81
|
+
"You should look at the implementation of #== on ",
|
82
|
+
"#{klass} or its members.\n",
|
83
|
+
expect,
|
86
84
|
].join
|
87
85
|
end
|
88
86
|
end
|
@@ -127,20 +125,15 @@ module Minitest
|
|
127
125
|
# See Minitest::Test.make_my_diffs_pretty!
|
128
126
|
|
129
127
|
def mu_pp obj
|
130
|
-
s = obj.inspect
|
128
|
+
s = obj.inspect.encode Encoding.default_external
|
131
129
|
|
132
|
-
|
133
|
-
|
130
|
+
return s unless String === obj &&
|
131
|
+
(obj.encoding != Encoding.default_external || !obj.valid_encoding?)
|
134
132
|
|
135
|
-
|
136
|
-
|
137
|
-
enc = "# encoding: #{obj.encoding}"
|
138
|
-
val = "# valid: #{obj.valid_encoding?}"
|
139
|
-
s = "#{enc}\n#{val}\n#{s}"
|
140
|
-
end
|
141
|
-
end
|
133
|
+
enc = "# encoding: #{obj.encoding}"
|
134
|
+
val = "# valid: #{obj.valid_encoding?}"
|
142
135
|
|
143
|
-
s
|
136
|
+
[enc, val, s].join "\n"
|
144
137
|
end
|
145
138
|
|
146
139
|
##
|
@@ -153,8 +146,8 @@ module Minitest
|
|
153
146
|
str = mu_pp obj
|
154
147
|
|
155
148
|
# both '\n' & '\\n' (_after_ mu_pp (aka inspect))
|
156
|
-
single =
|
157
|
-
double =
|
149
|
+
single = str.match?(/(?<!\\|^)\\n/)
|
150
|
+
double = str.match?(/(?<=\\|^)\\n/)
|
158
151
|
|
159
152
|
process =
|
160
153
|
if single ^ double then
|
@@ -167,9 +160,9 @@ module Minitest
|
|
167
160
|
:itself # leave it alone
|
168
161
|
end
|
169
162
|
|
170
|
-
str
|
171
|
-
gsub(/\\?\\n/, &process)
|
172
|
-
gsub(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX") # anonymize hex values
|
163
|
+
str
|
164
|
+
.gsub(/\\?\\n/, &process)
|
165
|
+
.gsub(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX") # anonymize hex values
|
173
166
|
end
|
174
167
|
|
175
168
|
##
|
@@ -193,11 +186,16 @@ module Minitest
|
|
193
186
|
# Fails unless +obj+ is empty.
|
194
187
|
|
195
188
|
def assert_empty obj, msg = nil
|
196
|
-
msg = message(msg) { "Expected #{mu_pp
|
189
|
+
msg = message(msg) { "Expected #{mu_pp obj} to be empty" }
|
197
190
|
assert_respond_to obj, :empty?
|
198
191
|
assert obj.empty?, msg
|
199
192
|
end
|
200
193
|
|
194
|
+
def _where # :nodoc:
|
195
|
+
Minitest.filter_backtrace(caller).first
|
196
|
+
.split(":in ", 2).first # clean up noise
|
197
|
+
end
|
198
|
+
|
201
199
|
E = "" # :nodoc:
|
202
200
|
|
203
201
|
##
|
@@ -218,13 +216,10 @@ module Minitest
|
|
218
216
|
result = assert exp == act, msg
|
219
217
|
|
220
218
|
if nil == exp then
|
221
|
-
if Minitest::VERSION
|
219
|
+
if Minitest::VERSION >= "6" then
|
222
220
|
refute_nil exp, "Use assert_nil if expecting nil."
|
223
221
|
else
|
224
|
-
|
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."
|
222
|
+
warn "DEPRECATED: Use assert_nil if expecting nil from #{_where}. This will fail in Minitest 6."
|
228
223
|
end
|
229
224
|
end
|
230
225
|
|
@@ -258,7 +253,7 @@ module Minitest
|
|
258
253
|
|
259
254
|
def assert_includes collection, obj, msg = nil
|
260
255
|
msg = message(msg) {
|
261
|
-
"Expected #{mu_pp
|
256
|
+
"Expected #{mu_pp collection} to include #{mu_pp obj}"
|
262
257
|
}
|
263
258
|
assert_respond_to collection, :include?
|
264
259
|
assert collection.include?(obj), msg
|
@@ -269,7 +264,7 @@ module Minitest
|
|
269
264
|
|
270
265
|
def assert_instance_of cls, obj, msg = nil
|
271
266
|
msg = message(msg) {
|
272
|
-
"Expected #{mu_pp
|
267
|
+
"Expected #{mu_pp obj} to be an instance of #{cls}, not #{obj.class}"
|
273
268
|
}
|
274
269
|
|
275
270
|
assert obj.instance_of?(cls), msg
|
@@ -280,7 +275,8 @@ module Minitest
|
|
280
275
|
|
281
276
|
def assert_kind_of cls, obj, msg = nil
|
282
277
|
msg = message(msg) {
|
283
|
-
"Expected #{mu_pp
|
278
|
+
"Expected #{mu_pp obj} to be a kind of #{cls}, not #{obj.class}"
|
279
|
+
}
|
284
280
|
|
285
281
|
assert obj.kind_of?(cls), msg
|
286
282
|
end
|
@@ -290,7 +286,7 @@ module Minitest
|
|
290
286
|
|
291
287
|
def assert_match matcher, obj, msg = nil
|
292
288
|
msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" }
|
293
|
-
assert_respond_to matcher,
|
289
|
+
assert_respond_to matcher, :=~
|
294
290
|
matcher = Regexp.new Regexp.escape matcher if String === matcher
|
295
291
|
assert matcher =~ obj, msg
|
296
292
|
|
@@ -301,7 +297,7 @@ module Minitest
|
|
301
297
|
# Fails unless +obj+ is nil
|
302
298
|
|
303
299
|
def assert_nil obj, msg = nil
|
304
|
-
msg = message(msg) { "Expected #{mu_pp
|
300
|
+
msg = message(msg) { "Expected #{mu_pp obj} to be nil" }
|
305
301
|
assert obj.nil?, msg
|
306
302
|
end
|
307
303
|
|
@@ -312,7 +308,7 @@ module Minitest
|
|
312
308
|
|
313
309
|
def assert_operator o1, op, o2 = UNDEFINED, msg = nil
|
314
310
|
return assert_predicate o1, op, msg if UNDEFINED == o2
|
315
|
-
msg = message(msg) { "Expected #{mu_pp
|
311
|
+
msg = message(msg) { "Expected #{mu_pp o1} to be #{op} #{mu_pp o2}" }
|
316
312
|
assert o1.__send__(op, o2), msg
|
317
313
|
end
|
318
314
|
|
@@ -357,6 +353,32 @@ module Minitest
|
|
357
353
|
assert File.exist?(path), msg
|
358
354
|
end
|
359
355
|
|
356
|
+
##
|
357
|
+
# For testing with pattern matching (only supported with Ruby 3.0 and later)
|
358
|
+
#
|
359
|
+
# # pass
|
360
|
+
# assert_pattern { [1,2,3] => [Integer, Integer, Integer] }
|
361
|
+
#
|
362
|
+
# # fail "length mismatch (given 3, expected 1)"
|
363
|
+
# assert_pattern { [1,2,3] => [Integer] }
|
364
|
+
#
|
365
|
+
# The bare <tt>=></tt> pattern will raise a NoMatchingPatternError on failure, which would
|
366
|
+
# normally be counted as a test error. This assertion rescues NoMatchingPatternError and
|
367
|
+
# generates a test failure. Any other exception will be raised as normal and generate a test
|
368
|
+
# error.
|
369
|
+
|
370
|
+
def assert_pattern
|
371
|
+
raise NotImplementedError, "only available in Ruby 3.0+" unless RUBY_VERSION >= "3.0"
|
372
|
+
flunk "assert_pattern requires a block to capture errors." unless block_given?
|
373
|
+
|
374
|
+
begin # TODO: remove after ruby 2.6 dropped
|
375
|
+
yield
|
376
|
+
pass
|
377
|
+
rescue NoMatchingPatternError => e
|
378
|
+
flunk e.message
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
360
382
|
##
|
361
383
|
# For testing with predicates. Eg:
|
362
384
|
#
|
@@ -367,7 +389,7 @@ module Minitest
|
|
367
389
|
# str.must_be :empty?
|
368
390
|
|
369
391
|
def assert_predicate o1, op, msg = nil
|
370
|
-
msg = message(msg) { "Expected #{mu_pp
|
392
|
+
msg = message(msg) { "Expected #{mu_pp o1} to be #{op}" }
|
371
393
|
assert o1.__send__(op), msg
|
372
394
|
end
|
373
395
|
|
@@ -412,23 +434,24 @@ module Minitest
|
|
412
434
|
raise
|
413
435
|
rescue Exception => e
|
414
436
|
flunk proc {
|
415
|
-
exception_details(e, "#{msg}#{mu_pp
|
437
|
+
exception_details(e, "#{msg}#{mu_pp exp} exception expected, not")
|
416
438
|
}
|
417
439
|
end
|
418
440
|
|
419
441
|
exp = exp.first if exp.size == 1
|
420
442
|
|
421
|
-
flunk "#{msg}#{mu_pp
|
443
|
+
flunk "#{msg}#{mu_pp exp} expected but nothing was raised."
|
422
444
|
end
|
423
445
|
|
424
446
|
##
|
425
447
|
# Fails unless +obj+ responds to +meth+.
|
448
|
+
# include_all defaults to false to match Object#respond_to?
|
426
449
|
|
427
|
-
def assert_respond_to obj, meth, msg = nil
|
450
|
+
def assert_respond_to obj, meth, msg = nil, include_all: false
|
428
451
|
msg = message(msg) {
|
429
|
-
"Expected #{mu_pp
|
452
|
+
"Expected #{mu_pp obj} (#{obj.class}) to respond to ##{meth}"
|
430
453
|
}
|
431
|
-
assert obj.respond_to?(meth), msg
|
454
|
+
assert obj.respond_to?(meth, include_all), msg
|
432
455
|
end
|
433
456
|
|
434
457
|
##
|
@@ -448,13 +471,12 @@ module Minitest
|
|
448
471
|
# Fails unless the call returns a true value
|
449
472
|
|
450
473
|
def assert_send send_ary, m = nil
|
451
|
-
|
452
|
-
where = where.split(/:in /, 2).first # clean up noise
|
453
|
-
warn "DEPRECATED: assert_send. From #{where}"
|
474
|
+
warn "DEPRECATED: assert_send. From #{_where}"
|
454
475
|
|
455
476
|
recv, msg, *args = send_ary
|
456
477
|
m = message(m) {
|
457
|
-
"Expected #{mu_pp
|
478
|
+
"Expected #{mu_pp recv}.#{msg}(*#{mu_pp args}) to return true"
|
479
|
+
}
|
458
480
|
assert recv.__send__(msg, *args), m
|
459
481
|
end
|
460
482
|
|
@@ -473,15 +495,15 @@ module Minitest
|
|
473
495
|
# Fails unless the block throws +sym+
|
474
496
|
|
475
497
|
def assert_throws sym, msg = nil
|
476
|
-
default = "Expected #{mu_pp
|
498
|
+
default = "Expected #{mu_pp sym} to have been thrown"
|
477
499
|
caught = true
|
478
|
-
value = catch
|
500
|
+
value = catch sym do
|
479
501
|
begin
|
480
502
|
yield
|
481
503
|
rescue ThreadError => e # wtf?!? 1.8 + threads == suck
|
482
|
-
default += ", not
|
504
|
+
default += ", not :#{e.message[/uncaught throw \`(\w+?)\'/, 1]}"
|
483
505
|
rescue ArgumentError => e # 1.9 exception
|
484
|
-
raise e unless e.message.include?
|
506
|
+
raise e unless e.message.include? "uncaught throw"
|
485
507
|
default += ", not #{e.message.split(/ /).last}"
|
486
508
|
rescue NameError => e # 1.8 exception
|
487
509
|
raise e unless e.name == sym
|
@@ -580,12 +602,12 @@ module Minitest
|
|
580
602
|
|
581
603
|
def exception_details e, msg
|
582
604
|
[
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
605
|
+
msg,
|
606
|
+
"Class: <#{e.class}>",
|
607
|
+
"Message: <#{e.message.inspect}>",
|
608
|
+
"---Backtrace---",
|
609
|
+
Minitest.filter_backtrace(e.backtrace),
|
610
|
+
"---------------",
|
589
611
|
].join "\n"
|
590
612
|
end
|
591
613
|
|
@@ -594,7 +616,7 @@ module Minitest
|
|
594
616
|
# you to put time-bombs in your tests if you need to keep
|
595
617
|
# something around until a later date lest you forget about it.
|
596
618
|
|
597
|
-
def fail_after y,m,d,msg
|
619
|
+
def fail_after y, m, d, msg
|
598
620
|
flunk msg if Time.now > Time.local(y, m, d)
|
599
621
|
end
|
600
622
|
|
@@ -628,7 +650,7 @@ module Minitest
|
|
628
650
|
# Fails if +test+ is truthy.
|
629
651
|
|
630
652
|
def refute test, msg = nil
|
631
|
-
msg ||= message { "Expected #{mu_pp
|
653
|
+
msg ||= message { "Expected #{mu_pp test} to not be truthy" }
|
632
654
|
assert !test, msg
|
633
655
|
end
|
634
656
|
|
@@ -636,7 +658,7 @@ module Minitest
|
|
636
658
|
# Fails if +obj+ is empty.
|
637
659
|
|
638
660
|
def refute_empty obj, msg = nil
|
639
|
-
msg = message(msg) { "Expected #{mu_pp
|
661
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not be empty" }
|
640
662
|
assert_respond_to obj, :empty?
|
641
663
|
refute obj.empty?, msg
|
642
664
|
end
|
@@ -648,7 +670,7 @@ module Minitest
|
|
648
670
|
|
649
671
|
def refute_equal exp, act, msg = nil
|
650
672
|
msg = message(msg) {
|
651
|
-
"Expected #{mu_pp
|
673
|
+
"Expected #{mu_pp act} to not be equal to #{mu_pp exp}"
|
652
674
|
}
|
653
675
|
refute exp == act, msg
|
654
676
|
end
|
@@ -679,7 +701,7 @@ module Minitest
|
|
679
701
|
|
680
702
|
def refute_includes collection, obj, msg = nil
|
681
703
|
msg = message(msg) {
|
682
|
-
"Expected #{mu_pp
|
704
|
+
"Expected #{mu_pp collection} to not include #{mu_pp obj}"
|
683
705
|
}
|
684
706
|
assert_respond_to collection, :include?
|
685
707
|
refute collection.include?(obj), msg
|
@@ -690,7 +712,7 @@ module Minitest
|
|
690
712
|
|
691
713
|
def refute_instance_of cls, obj, msg = nil
|
692
714
|
msg = message(msg) {
|
693
|
-
"Expected #{mu_pp
|
715
|
+
"Expected #{mu_pp obj} to not be an instance of #{cls}"
|
694
716
|
}
|
695
717
|
refute obj.instance_of?(cls), msg
|
696
718
|
end
|
@@ -699,7 +721,7 @@ module Minitest
|
|
699
721
|
# Fails if +obj+ is a kind of +cls+.
|
700
722
|
|
701
723
|
def refute_kind_of cls, obj, msg = nil
|
702
|
-
msg = message(msg) { "Expected #{mu_pp
|
724
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not be a kind of #{cls}" }
|
703
725
|
refute obj.kind_of?(cls), msg
|
704
726
|
end
|
705
727
|
|
@@ -708,7 +730,7 @@ module Minitest
|
|
708
730
|
|
709
731
|
def refute_match matcher, obj, msg = nil
|
710
732
|
msg = message(msg) { "Expected #{mu_pp matcher} to not match #{mu_pp obj}" }
|
711
|
-
assert_respond_to matcher,
|
733
|
+
assert_respond_to matcher, :=~
|
712
734
|
matcher = Regexp.new Regexp.escape matcher if String === matcher
|
713
735
|
refute matcher =~ obj, msg
|
714
736
|
end
|
@@ -717,10 +739,34 @@ module Minitest
|
|
717
739
|
# Fails if +obj+ is nil.
|
718
740
|
|
719
741
|
def refute_nil obj, msg = nil
|
720
|
-
msg = message(msg) { "Expected #{mu_pp
|
742
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not be nil" }
|
721
743
|
refute obj.nil?, msg
|
722
744
|
end
|
723
745
|
|
746
|
+
##
|
747
|
+
# For testing with pattern matching (only supported with Ruby 3.0 and later)
|
748
|
+
#
|
749
|
+
# # pass
|
750
|
+
# refute_pattern { [1,2,3] => [String] }
|
751
|
+
#
|
752
|
+
# # fail "NoMatchingPatternError expected, but nothing was raised."
|
753
|
+
# refute_pattern { [1,2,3] => [Integer, Integer, Integer] }
|
754
|
+
#
|
755
|
+
# This assertion expects a NoMatchingPatternError exception, and will fail if none is raised. Any
|
756
|
+
# other exceptions will be raised as normal and generate a test error.
|
757
|
+
|
758
|
+
def refute_pattern
|
759
|
+
raise NotImplementedError, "only available in Ruby 3.0+" unless RUBY_VERSION >= "3.0"
|
760
|
+
flunk "refute_pattern requires a block to capture errors." unless block_given?
|
761
|
+
|
762
|
+
begin
|
763
|
+
yield
|
764
|
+
flunk "NoMatchingPatternError expected, but nothing was raised."
|
765
|
+
rescue NoMatchingPatternError
|
766
|
+
pass
|
767
|
+
end
|
768
|
+
end
|
769
|
+
|
724
770
|
##
|
725
771
|
# Fails if +o1+ is not +op+ +o2+. Eg:
|
726
772
|
#
|
@@ -729,7 +775,7 @@ module Minitest
|
|
729
775
|
|
730
776
|
def refute_operator o1, op, o2 = UNDEFINED, msg = nil
|
731
777
|
return refute_predicate o1, op, msg if UNDEFINED == o2
|
732
|
-
msg = message(msg) { "Expected #{mu_pp
|
778
|
+
msg = message(msg) { "Expected #{mu_pp o1} to not be #{op} #{mu_pp o2}" }
|
733
779
|
refute o1.__send__(op, o2), msg
|
734
780
|
end
|
735
781
|
|
@@ -751,17 +797,18 @@ module Minitest
|
|
751
797
|
# str.wont_be :empty?
|
752
798
|
|
753
799
|
def refute_predicate o1, op, msg = nil
|
754
|
-
msg = message(msg) { "Expected #{mu_pp
|
800
|
+
msg = message(msg) { "Expected #{mu_pp o1} to not be #{op}" }
|
755
801
|
refute o1.__send__(op), msg
|
756
802
|
end
|
757
803
|
|
758
804
|
##
|
759
805
|
# Fails if +obj+ responds to the message +meth+.
|
806
|
+
# include_all defaults to false to match Object#respond_to?
|
760
807
|
|
761
|
-
def refute_respond_to obj, meth, msg = nil
|
762
|
-
msg = message(msg) { "Expected #{mu_pp
|
808
|
+
def refute_respond_to obj, meth, msg = nil, include_all: false
|
809
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not respond to #{meth}" }
|
763
810
|
|
764
|
-
refute obj.respond_to?(meth), msg
|
811
|
+
refute obj.respond_to?(meth, include_all), msg
|
765
812
|
end
|
766
813
|
|
767
814
|
##
|
@@ -780,10 +827,10 @@ module Minitest
|
|
780
827
|
# gets listed at the end of the run but doesn't cause a failure
|
781
828
|
# exit code.
|
782
829
|
|
783
|
-
def skip msg = nil,
|
830
|
+
def skip msg = nil, _ignored = nil
|
784
831
|
msg ||= "Skipped, no message given"
|
785
832
|
@skip = true
|
786
|
-
raise Minitest::Skip, msg
|
833
|
+
raise Minitest::Skip, msg
|
787
834
|
end
|
788
835
|
|
789
836
|
##
|
@@ -792,9 +839,9 @@ module Minitest
|
|
792
839
|
# date, but still holds you accountable and prevents you from
|
793
840
|
# forgetting it.
|
794
841
|
|
795
|
-
def skip_until y,m,d,msg
|
842
|
+
def skip_until y, m, d, msg
|
796
843
|
skip msg if Time.now < Time.local(y, m, d)
|
797
|
-
where = caller.first.rpartition(
|
844
|
+
where = caller(1..1).first.rpartition(":in").reject(&:empty?).first
|
798
845
|
warn "Stale skip_until %p at %s" % [msg, where]
|
799
846
|
end
|
800
847
|
|
data/lib/minitest/autorun.rb
CHANGED
data/lib/minitest/benchmark.rb
CHANGED
@@ -47,8 +47,6 @@ module Minitest
|
|
47
47
|
|
48
48
|
def self.bench_linear min, max, step = 10
|
49
49
|
(min..max).step(step).to_a
|
50
|
-
rescue LocalJumpError # 1.8.6
|
51
|
-
r = []; (min..max).step(step) { |n| r << n }; r
|
52
50
|
end
|
53
51
|
|
54
52
|
##
|
@@ -83,7 +81,7 @@ module Minitest
|
|
83
81
|
def assert_performance validation, &work
|
84
82
|
range = self.class.bench_range
|
85
83
|
|
86
|
-
io.print
|
84
|
+
io.print self.name
|
87
85
|
|
88
86
|
times = []
|
89
87
|
|
@@ -236,7 +234,7 @@ module Minitest
|
|
236
234
|
|
237
235
|
def fit_exponential xs, ys
|
238
236
|
n = xs.size
|
239
|
-
xys = xs.zip
|
237
|
+
xys = xs.zip ys
|
240
238
|
sxlny = sigma(xys) { |x, y| x * Math.log(y) }
|
241
239
|
slny = sigma(xys) { |_, y| Math.log(y) }
|
242
240
|
sx2 = sigma(xys) { |x, _| x * x }
|
@@ -258,7 +256,7 @@ module Minitest
|
|
258
256
|
|
259
257
|
def fit_logarithmic xs, ys
|
260
258
|
n = xs.size
|
261
|
-
xys = xs.zip
|
259
|
+
xys = xs.zip ys
|
262
260
|
slnx2 = sigma(xys) { |x, _| Math.log(x) ** 2 }
|
263
261
|
slnx = sigma(xys) { |x, _| Math.log(x) }
|
264
262
|
sylnx = sigma(xys) { |x, y| y * Math.log(x) }
|
@@ -280,7 +278,7 @@ module Minitest
|
|
280
278
|
|
281
279
|
def fit_linear xs, ys
|
282
280
|
n = xs.size
|
283
|
-
xys = xs.zip
|
281
|
+
xys = xs.zip ys
|
284
282
|
sx = sigma xs
|
285
283
|
sy = sigma ys
|
286
284
|
sx2 = sigma(xs) { |x| x ** 2 }
|
@@ -302,7 +300,7 @@ module Minitest
|
|
302
300
|
|
303
301
|
def fit_power xs, ys
|
304
302
|
n = xs.size
|
305
|
-
xys = xs.zip
|
303
|
+
xys = xs.zip ys
|
306
304
|
slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) }
|
307
305
|
slnx = sigma(xs) { |x | Math.log(x) }
|
308
306
|
slny = sigma(ys) { | y| Math.log(y) }
|
@@ -323,7 +321,7 @@ module Minitest
|
|
323
321
|
|
324
322
|
def sigma enum, &block
|
325
323
|
enum = enum.map(&block) if block
|
326
|
-
enum.
|
324
|
+
enum.sum
|
327
325
|
end
|
328
326
|
|
329
327
|
##
|
@@ -419,7 +417,6 @@ module Minitest
|
|
419
417
|
end
|
420
418
|
end
|
421
419
|
|
422
|
-
|
423
420
|
##
|
424
421
|
# Create a benchmark that verifies that the performance is logarithmic.
|
425
422
|
#
|
@@ -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 = ->(a, n, off) { # each_slice_with_offset
|
15
|
+
if off.zero? then
|
16
|
+
a.each_slice n
|
17
|
+
else
|
18
|
+
# [ ...off... [...n...] [...n...] ... ]
|
19
|
+
front, back = a.take(off), a.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, a1| ### sort by max dist + min offset
|
33
|
+
d = a1.each_cons(2).sum { |a2, b| b-a2 }
|
34
|
+
[-d, a1.first]
|
35
|
+
} # b: [1 3 5] c: [2 4 6]
|
36
|
+
|
37
|
+
ranges = order
|
38
|
+
.map { |k, a1| # [[1..2 3..4] [2..3 4..5]]
|
39
|
+
a1
|
40
|
+
.each_cons(2)
|
41
|
+
.map { |a2, b| a2..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
|