minitest 5.10.3 → 5.18.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.
data/lib/hoe/minitest.rb CHANGED
@@ -24,9 +24,5 @@ module Hoe::Minitest
24
24
 
25
25
  def define_minitest_tasks
26
26
  self.testlib = :minitest
27
-
28
- # make sure we use the gemmed minitest on 1.9
29
- self.test_prelude = 'gem "minitest"' unless
30
- minitest? or ENV["MT_NO_ISOLATE"]
31
27
  end
32
28
  end
@@ -27,20 +27,18 @@ module Minitest
27
27
  # figure out what diff to use.
28
28
 
29
29
  def self.diff
30
+ return @diff if defined? @diff
31
+
30
32
  @diff = if (RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ &&
31
33
  system("diff.exe", __FILE__, __FILE__)) then
32
34
  "diff.exe -u"
33
- elsif Minitest::Test.maglev? then
34
- "diff -u"
35
35
  elsif system("gdiff", __FILE__, __FILE__)
36
36
  "gdiff -u" # solaris and kin suck
37
37
  elsif system("diff", __FILE__, __FILE__)
38
38
  "diff -u"
39
39
  else
40
40
  nil
41
- end unless defined? @diff
42
-
43
- @diff
41
+ end
44
42
  end
45
43
 
46
44
  ##
@@ -55,22 +53,16 @@ module Minitest
55
53
  # diff command or if it doesn't make sense to diff the output
56
54
  # (single line, short output), then it simply returns a basic
57
55
  # comparison between the two.
56
+ #
57
+ # See +things_to_diff+ for more info.
58
58
 
59
59
  def diff exp, act
60
- expect = mu_pp_for_diff exp
61
- butwas = mu_pp_for_diff act
62
60
  result = nil
63
61
 
64
- need_to_diff =
65
- (expect.include?("\n") ||
66
- butwas.include?("\n") ||
67
- expect.size > 30 ||
68
- butwas.size > 30 ||
69
- expect == butwas) &&
70
- Minitest::Assertions.diff
62
+ expect, butwas = things_to_diff(exp, act)
71
63
 
72
64
  return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless
73
- need_to_diff
65
+ expect
74
66
 
75
67
  Tempfile.open("expect") do |a|
76
68
  a.puts expect
@@ -99,10 +91,40 @@ module Minitest
99
91
  result
100
92
  end
101
93
 
94
+ ##
95
+ # Returns things to diff [expect, butwas], or [nil, nil] if nothing to diff.
96
+ #
97
+ # Criterion:
98
+ #
99
+ # 1. Strings include newlines or escaped newlines, but not both.
100
+ # 2. or: String lengths are > 30 characters.
101
+ # 3. or: Strings are equal to each other (but maybe different encodings?).
102
+ # 4. and: we found a diff executable.
103
+
104
+ def things_to_diff exp, act
105
+ expect = mu_pp_for_diff exp
106
+ butwas = mu_pp_for_diff act
107
+
108
+ e1, e2 = expect.include?("\n"), expect.include?("\\n")
109
+ b1, b2 = butwas.include?("\n"), butwas.include?("\\n")
110
+
111
+ need_to_diff =
112
+ (e1 ^ e2 ||
113
+ b1 ^ b2 ||
114
+ expect.size > 30 ||
115
+ butwas.size > 30 ||
116
+ expect == butwas) &&
117
+ Minitest::Assertions.diff
118
+
119
+ need_to_diff && [expect, butwas]
120
+ end
121
+
102
122
  ##
103
123
  # This returns a human-readable version of +obj+. By default
104
- # #inspect is called. You can override this to use #pretty_print
124
+ # #inspect is called. You can override this to use #pretty_inspect
105
125
  # if you want.
126
+ #
127
+ # See Minitest::Test.make_my_diffs_pretty!
106
128
 
107
129
  def mu_pp obj
108
130
  s = obj.inspect
@@ -110,8 +132,11 @@ module Minitest
110
132
  if defined? Encoding then
111
133
  s = s.encode Encoding.default_external
112
134
 
113
- if String === obj && obj.encoding != Encoding.default_external then
114
- s = "# encoding: #{obj.encoding}\n#{s}"
135
+ if String === obj && (obj.encoding != Encoding.default_external ||
136
+ !obj.valid_encoding?) then
137
+ enc = "# encoding: #{obj.encoding}"
138
+ val = "# valid: #{obj.valid_encoding?}"
139
+ s = "#{enc}\n#{val}\n#{s}"
115
140
  end
116
141
  end
117
142
 
@@ -119,13 +144,32 @@ module Minitest
119
144
  end
120
145
 
121
146
  ##
122
- # This returns a diff-able human-readable version of +obj+. This
123
- # differs from the regular mu_pp because it expands escaped
124
- # newlines and makes hex-values generic (like object_ids). This
147
+ # This returns a diff-able more human-readable version of +obj+.
148
+ # This differs from the regular mu_pp because it expands escaped
149
+ # newlines and makes hex-values (like object_ids) generic. This
125
150
  # uses mu_pp to do the first pass and then cleans it up.
126
151
 
127
152
  def mu_pp_for_diff obj
128
- mu_pp(obj).gsub(/\\n/, "\n").gsub(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX")
153
+ str = mu_pp obj
154
+
155
+ # both '\n' & '\\n' (_after_ mu_pp (aka inspect))
156
+ single = !!str.match(/(?<!\\|^)\\n/)
157
+ double = !!str.match(/(?<=\\|^)\\n/)
158
+
159
+ process =
160
+ if single ^ double then
161
+ if single then
162
+ lambda { |s| s == "\\n" ? "\n" : s } # unescape
163
+ else
164
+ lambda { |s| s == "\\\\n" ? "\\n\n" : s } # unescape a bit, add nls
165
+ end
166
+ else
167
+ :itself # leave it alone
168
+ end
169
+
170
+ str.
171
+ gsub(/\\?\\n/, &process).
172
+ gsub(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX") # anonymize hex values
129
173
  end
130
174
 
131
175
  ##
@@ -173,7 +217,7 @@ module Minitest
173
217
  msg = message(msg, E) { diff exp, act }
174
218
  result = assert exp == act, msg
175
219
 
176
- if exp.nil? then
220
+ if nil == exp then
177
221
  if Minitest::VERSION =~ /^6/ then
178
222
  refute_nil exp, "Use assert_nil if expecting nil."
179
223
  else
@@ -205,8 +249,8 @@ module Minitest
205
249
  # For comparing Floats. Fails unless +exp+ and +act+ have a relative
206
250
  # error less than +epsilon+.
207
251
 
208
- def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
209
- assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg
252
+ def assert_in_epsilon exp, act, epsilon = 0.001, msg = nil
253
+ assert_in_delta exp, act, [exp.abs, act.abs].min * epsilon, msg
210
254
  end
211
255
 
212
256
  ##
@@ -249,6 +293,8 @@ module Minitest
249
293
  assert_respond_to matcher, :"=~"
250
294
  matcher = Regexp.new Regexp.escape matcher if String === matcher
251
295
  assert matcher =~ obj, msg
296
+
297
+ Regexp.last_match
252
298
  end
253
299
 
254
300
  ##
@@ -283,6 +329,9 @@ module Minitest
283
329
  # See also: #assert_silent
284
330
 
285
331
  def assert_output stdout = nil, stderr = nil
332
+ flunk "assert_output requires a block to capture output." unless
333
+ block_given?
334
+
286
335
  out, err = capture_io do
287
336
  yield
288
337
  end
@@ -294,6 +343,44 @@ module Minitest
294
343
  x = send out_msg, stdout, out, "In stdout" if out_msg
295
344
 
296
345
  (!stdout || x) && (!stderr || y)
346
+ rescue Assertion
347
+ raise
348
+ rescue => e
349
+ raise UnexpectedError, e
350
+ end
351
+
352
+ ##
353
+ # Fails unless +path+ exists.
354
+
355
+ def assert_path_exists path, msg = nil
356
+ msg = message(msg) { "Expected path '#{path}' to exist" }
357
+ assert File.exist?(path), msg
358
+ end
359
+
360
+ ##
361
+ # For testing with pattern matching (only supported with Ruby 3.0 and later)
362
+ #
363
+ # # pass
364
+ # assert_pattern { [1,2,3] => [Integer, Integer, Integer] }
365
+ #
366
+ # # fail "length mismatch (given 3, expected 1)"
367
+ # assert_pattern { [1,2,3] => [Integer] }
368
+ #
369
+ # The bare <tt>=></tt> pattern will raise a NoMatchingPatternError on failure, which would
370
+ # normally be counted as a test error. This assertion rescues NoMatchingPatternError and
371
+ # generates a test failure. Any other exception will be raised as normal and generate a test
372
+ # error.
373
+
374
+ def assert_pattern
375
+ raise NotImplementedError, "only available in Ruby 3.0+" unless RUBY_VERSION >= "3.0"
376
+ flunk "assert_pattern requires a block to capture errors." unless block_given?
377
+
378
+ begin # TODO: remove after ruby 2.6 dropped
379
+ yield
380
+ pass
381
+ rescue NoMatchingPatternError => e
382
+ flunk e.message
383
+ end
297
384
  end
298
385
 
299
386
  ##
@@ -316,9 +403,26 @@ module Minitest
316
403
  #
317
404
  # +exp+ takes an optional message on the end to help explain
318
405
  # failures and defaults to StandardError if no exception class is
319
- # passed.
406
+ # passed. Eg:
407
+ #
408
+ # assert_raises(CustomError) { method_with_custom_error }
409
+ #
410
+ # With custom error message:
411
+ #
412
+ # assert_raises(CustomError, 'This should have raised CustomError') { method_with_custom_error }
413
+ #
414
+ # Using the returned object:
415
+ #
416
+ # error = assert_raises(CustomError) do
417
+ # raise CustomError, 'This is really bad'
418
+ # end
419
+ #
420
+ # assert_equal 'This is really bad', error.message
320
421
 
321
422
  def assert_raises *exp
423
+ flunk "assert_raises requires a block to capture errors." unless
424
+ block_given?
425
+
322
426
  msg = "#{exp.pop}.\n" if String === exp.last
323
427
  exp << StandardError if exp.empty?
324
428
 
@@ -327,7 +431,7 @@ module Minitest
327
431
  rescue *exp => e
328
432
  pass # count assertion
329
433
  return e
330
- rescue Minitest::Skip, Minitest::Assertion
434
+ rescue Minitest::Assertion # incl Skip & UnexpectedError
331
435
  # don't count assertion
332
436
  raise
333
437
  rescue SignalException, SystemExit
@@ -397,7 +501,7 @@ module Minitest
397
501
  def assert_throws sym, msg = nil
398
502
  default = "Expected #{mu_pp(sym)} to have been thrown"
399
503
  caught = true
400
- catch(sym) do
504
+ value = catch(sym) do
401
505
  begin
402
506
  yield
403
507
  rescue ThreadError => e # wtf?!? 1.8 + threads == suck
@@ -413,6 +517,11 @@ module Minitest
413
517
  end
414
518
 
415
519
  assert caught, message(msg) { default }
520
+ value
521
+ rescue Assertion
522
+ raise
523
+ rescue => e
524
+ raise UnexpectedError, e
416
525
  end
417
526
 
418
527
  ##
@@ -481,10 +590,13 @@ module Minitest
481
590
 
482
591
  return captured_stdout.read, captured_stderr.read
483
592
  ensure
484
- captured_stdout.unlink
485
- captured_stderr.unlink
486
593
  $stdout.reopen orig_stdout
487
594
  $stderr.reopen orig_stderr
595
+
596
+ orig_stdout.close
597
+ orig_stderr.close
598
+ captured_stdout.close!
599
+ captured_stderr.close!
488
600
  end
489
601
  end
490
602
  end
@@ -504,7 +616,16 @@ module Minitest
504
616
  end
505
617
 
506
618
  ##
507
- # Fails with +msg+
619
+ # Fails after a given date (in the local time zone). This allows
620
+ # you to put time-bombs in your tests if you need to keep
621
+ # something around until a later date lest you forget about it.
622
+
623
+ def fail_after y,m,d,msg
624
+ flunk msg if Time.now > Time.local(y, m, d)
625
+ end
626
+
627
+ ##
628
+ # Fails with +msg+.
508
629
 
509
630
  def flunk msg = nil
510
631
  msg ||= "Epic Fail!"
@@ -534,7 +655,7 @@ module Minitest
534
655
 
535
656
  def refute test, msg = nil
536
657
  msg ||= message { "Expected #{mu_pp(test)} to not be truthy" }
537
- not assert !test, msg
658
+ assert !test, msg
538
659
  end
539
660
 
540
661
  ##
@@ -626,6 +747,30 @@ module Minitest
626
747
  refute obj.nil?, msg
627
748
  end
628
749
 
750
+ ##
751
+ # For testing with pattern matching (only supported with Ruby 3.0 and later)
752
+ #
753
+ # # pass
754
+ # refute_pattern { [1,2,3] => [String] }
755
+ #
756
+ # # fail "NoMatchingPatternError expected, but nothing was raised."
757
+ # refute_pattern { [1,2,3] => [Integer, Integer, Integer] }
758
+ #
759
+ # This assertion expects a NoMatchingPatternError exception, and will fail if none is raised. Any
760
+ # other exceptions will be raised as normal and generate a test error.
761
+
762
+ def refute_pattern
763
+ raise NotImplementedError, "only available in Ruby 3.0+" unless RUBY_VERSION >= "3.0"
764
+ flunk "refute_pattern requires a block to capture errors." unless block_given?
765
+
766
+ begin
767
+ yield
768
+ flunk("NoMatchingPatternError expected, but nothing was raised.")
769
+ rescue NoMatchingPatternError
770
+ pass
771
+ end
772
+ end
773
+
629
774
  ##
630
775
  # Fails if +o1+ is not +op+ +o2+. Eg:
631
776
  #
@@ -638,6 +783,14 @@ module Minitest
638
783
  refute o1.__send__(op, o2), msg
639
784
  end
640
785
 
786
+ ##
787
+ # Fails if +path+ exists.
788
+
789
+ def refute_path_exists path, msg = nil
790
+ msg = message(msg) { "Expected path '#{path}' to not exist" }
791
+ refute File.exist?(path), msg
792
+ end
793
+
641
794
  ##
642
795
  # For testing with predicates.
643
796
  #
@@ -683,6 +836,18 @@ module Minitest
683
836
  raise Minitest::Skip, msg, bt
684
837
  end
685
838
 
839
+ ##
840
+ # Skips the current run until a given date (in the local time
841
+ # zone). This allows you to put some fixes on hold until a later
842
+ # date, but still holds you accountable and prevents you from
843
+ # forgetting it.
844
+
845
+ def skip_until y,m,d,msg
846
+ skip msg if Time.now < Time.local(y, m, d)
847
+ where = caller.first.rpartition(':in').reject(&:empty?).first
848
+ warn "Stale skip_until %p at %s" % [msg, where]
849
+ end
850
+
686
851
  ##
687
852
  # Was this testcase skipped? Meant for #teardown.
688
853
 
@@ -109,8 +109,8 @@ module Minitest
109
109
  # is applied against the slope itself. As such, you probably want
110
110
  # to tighten it from the default.
111
111
  #
112
- # See http://www.graphpad.com/curvefit/goodness_of_fit.htm for
113
- # more details.
112
+ # See https://www.graphpad.com/guides/prism/8/curve-fitting/reg_intepretingnonlinr2.htm
113
+ # for more details.
114
114
  #
115
115
  # Fit is calculated by #fit_linear.
116
116
  #
@@ -217,7 +217,7 @@ module Minitest
217
217
  ##
218
218
  # Takes an array of x/y pairs and calculates the general R^2 value.
219
219
  #
220
- # See: http://en.wikipedia.org/wiki/Coefficient_of_determination
220
+ # See: https://en.wikipedia.org/wiki/Coefficient_of_determination
221
221
 
222
222
  def fit_error xys
223
223
  y_bar = sigma(xys) { |_, y| y } / xys.size.to_f
@@ -232,7 +232,7 @@ module Minitest
232
232
  #
233
233
  # Takes x and y values and returns [a, b, r^2].
234
234
  #
235
- # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html
235
+ # See: https://mathworld.wolfram.com/LeastSquaresFittingExponential.html
236
236
 
237
237
  def fit_exponential xs, ys
238
238
  n = xs.size
@@ -254,7 +254,7 @@ module Minitest
254
254
  #
255
255
  # Takes x and y values and returns [a, b, r^2].
256
256
  #
257
- # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html
257
+ # See: https://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html
258
258
 
259
259
  def fit_logarithmic xs, ys
260
260
  n = xs.size
@@ -276,7 +276,7 @@ module Minitest
276
276
  #
277
277
  # Takes x and y values and returns [a, b, r^2].
278
278
  #
279
- # See: http://mathworld.wolfram.com/LeastSquaresFitting.html
279
+ # See: https://mathworld.wolfram.com/LeastSquaresFitting.html
280
280
 
281
281
  def fit_linear xs, ys
282
282
  n = xs.size
@@ -298,7 +298,7 @@ module Minitest
298
298
  #
299
299
  # Takes x and y values and returns [a, b, r^2].
300
300
  #
301
- # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html
301
+ # See: https://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html
302
302
 
303
303
  def fit_power xs, ys
304
304
  n = xs.size
@@ -318,7 +318,7 @@ module Minitest
318
318
  # Enumerates over +enum+ mapping +block+ if given, returning the
319
319
  # sum of the result. Eg:
320
320
  #
321
- # sigma([1, 2, 3]) # => 1 + 2 + 3 => 7
321
+ # sigma([1, 2, 3]) # => 1 + 2 + 3 => 6
322
322
  # sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14
323
323
 
324
324
  def sigma enum, &block
@@ -418,6 +418,37 @@ module Minitest
418
418
  assert_performance_exponential threshold, &work
419
419
  end
420
420
  end
421
+
422
+
423
+ ##
424
+ # Create a benchmark that verifies that the performance is logarithmic.
425
+ #
426
+ # describe "my class Bench" do
427
+ # bench_performance_logarithmic "algorithm" do |n|
428
+ # @obj.algorithm(n)
429
+ # end
430
+ # end
431
+
432
+ def self.bench_performance_logarithmic name, threshold = 0.99, &work
433
+ bench name do
434
+ assert_performance_logarithmic threshold, &work
435
+ end
436
+ end
437
+
438
+ ##
439
+ # Create a benchmark that verifies that the performance is power.
440
+ #
441
+ # describe "my class Bench" do
442
+ # bench_performance_power "algorithm" do |n|
443
+ # @obj.algorithm(n)
444
+ # end
445
+ # end
446
+
447
+ def self.bench_performance_power name, threshold = 0.99, &work
448
+ bench name do
449
+ assert_performance_power threshold, &work
450
+ end
451
+ end
421
452
  end
422
453
 
423
454
  Minitest::Spec.register_spec_type(/Bench(mark)?$/, Minitest::BenchSpec)