minitest 1.7.2 → 2.0.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/History.txt +27 -0
- data/Manifest.txt +6 -3
- data/README.txt +133 -67
- data/lib/minitest/benchmark.rb +324 -0
- data/lib/minitest/mock.rb +14 -7
- data/lib/minitest/pride.rb +35 -0
- data/lib/minitest/spec.rb +8 -5
- data/lib/minitest/unit.rb +179 -86
- data/test/test_minitest_benchmark.rb +98 -0
- data/test/test_minitest_mock.rb +106 -0
- data/test/{test_mini_spec.rb → test_minitest_spec.rb} +12 -2
- data/test/{test_mini_test.rb → test_minitest_unit.rb} +51 -73
- metadata +38 -18
- data/test/test_mini_mock.rb +0 -77
data/lib/minitest/mock.rb
CHANGED
@@ -8,14 +8,7 @@ module MiniTest
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def expect(name, retval, args=[])
|
11
|
-
n, r, a = name, retval, args # for the closure below
|
12
11
|
@expected_calls[name] = { :retval => retval, :args => args }
|
13
|
-
self.class.__send__ :remove_method, name if respond_to? name
|
14
|
-
self.class.__send__(:define_method, name) { |*x|
|
15
|
-
raise ArgumentError unless @expected_calls[n][:args].size == x.size
|
16
|
-
@actual_calls[n] << { :retval => r, :args => x }
|
17
|
-
retval
|
18
|
-
}
|
19
12
|
self
|
20
13
|
end
|
21
14
|
|
@@ -28,5 +21,19 @@ module MiniTest
|
|
28
21
|
end
|
29
22
|
true
|
30
23
|
end
|
24
|
+
|
25
|
+
def method_missing(sym, *args)
|
26
|
+
raise NoMethodError unless @expected_calls.has_key?(sym)
|
27
|
+
raise ArgumentError unless @expected_calls[sym][:args].size == args.size
|
28
|
+
retval = @expected_calls[sym][:retval]
|
29
|
+
@actual_calls[sym] << { :retval => retval, :args => args }
|
30
|
+
retval
|
31
|
+
end
|
32
|
+
|
33
|
+
alias :original_respond_to? :respond_to?
|
34
|
+
def respond_to?(sym)
|
35
|
+
return true if @expected_calls.has_key?(sym)
|
36
|
+
return original_respond_to?(sym)
|
37
|
+
end
|
31
38
|
end
|
32
39
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "minitest/unit"
|
2
|
+
|
3
|
+
##
|
4
|
+
# Show your testing pride!
|
5
|
+
|
6
|
+
class PrideIO
|
7
|
+
attr_reader :io
|
8
|
+
|
9
|
+
# stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm
|
10
|
+
COLORS = (31..36).to_a
|
11
|
+
CHARS = ["*"]
|
12
|
+
|
13
|
+
def initialize io
|
14
|
+
@io = io
|
15
|
+
@colors = COLORS.cycle
|
16
|
+
@chars = CHARS.cycle
|
17
|
+
end
|
18
|
+
|
19
|
+
def print o
|
20
|
+
case o
|
21
|
+
when "." then
|
22
|
+
io.print "\e[#{@colors.next}m#{@chars.next}\e[0m"
|
23
|
+
when "E", "F" then
|
24
|
+
io.print "\e[41m\e[37m#{o}\e[0m"
|
25
|
+
else
|
26
|
+
io.print o
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing msg, *args
|
31
|
+
io.send(msg, *args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
MiniTest::Unit.output = PrideIO.new(MiniTest::Unit.output)
|
data/lib/minitest/spec.rb
CHANGED
@@ -60,10 +60,13 @@ module Kernel
|
|
60
60
|
|
61
61
|
def describe desc, &block
|
62
62
|
stack = MiniTest::Spec.describe_stack
|
63
|
-
name =
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
name = [stack.last, desc].compact.join("::")
|
64
|
+
cls = Class.new(stack.last || MiniTest::Spec)
|
65
|
+
|
66
|
+
# :stopdoc:
|
67
|
+
# omg this sucks
|
68
|
+
(class << cls; self; end).send(:define_method, :to_s) { name }
|
69
|
+
# :startdoc:
|
67
70
|
|
68
71
|
cls.nuke_test_methods!
|
69
72
|
|
@@ -90,7 +93,7 @@ end
|
|
90
93
|
|
91
94
|
|
92
95
|
class MiniTest::Spec < MiniTest::Unit::TestCase
|
93
|
-
@@describe_stack = [
|
96
|
+
@@describe_stack = []
|
94
97
|
def self.describe_stack # :nodoc:
|
95
98
|
@@describe_stack
|
96
99
|
end
|
data/lib/minitest/unit.rb
CHANGED
@@ -2,6 +2,8 @@ require 'optparse'
|
|
2
2
|
|
3
3
|
##
|
4
4
|
# Minimal (mostly drop-in) replacement for test-unit.
|
5
|
+
#
|
6
|
+
# :include: README.txt
|
5
7
|
|
6
8
|
module MiniTest
|
7
9
|
|
@@ -21,7 +23,8 @@ module MiniTest
|
|
21
23
|
require 'pathname'
|
22
24
|
pwd = Pathname.new Dir.pwd
|
23
25
|
pn = Pathname.new File.expand_path(__FILE__)
|
24
|
-
|
26
|
+
relpath = pn.relative_path_from(pwd) rescue pn
|
27
|
+
pn = File.join ".", relpath unless pn.relative?
|
25
28
|
pn.to_s
|
26
29
|
else # assume both are expanded
|
27
30
|
__FILE__
|
@@ -35,11 +38,11 @@ module MiniTest
|
|
35
38
|
|
36
39
|
new_bt = []
|
37
40
|
bt.each do |line|
|
38
|
-
break if line.rindex
|
41
|
+
break if line.rindex MINI_DIR, 0
|
39
42
|
new_bt << line
|
40
43
|
end
|
41
44
|
|
42
|
-
new_bt = bt.reject { |line| line.rindex
|
45
|
+
new_bt = bt.reject { |line| line.rindex MINI_DIR, 0 } if new_bt.empty?
|
43
46
|
new_bt = bt.dup if new_bt.empty?
|
44
47
|
new_bt
|
45
48
|
end
|
@@ -56,7 +59,7 @@ module MiniTest
|
|
56
59
|
|
57
60
|
def mu_pp obj
|
58
61
|
s = obj.inspect
|
59
|
-
s = s.force_encoding
|
62
|
+
s = s.force_encoding Encoding.default_external if defined? Encoding
|
60
63
|
s
|
61
64
|
end
|
62
65
|
|
@@ -85,15 +88,14 @@ module MiniTest
|
|
85
88
|
# Fails unless the block returns a true value.
|
86
89
|
|
87
90
|
def assert_block msg = nil
|
88
|
-
|
89
|
-
assert yield, msg
|
91
|
+
assert yield, "Expected block to return true value."
|
90
92
|
end
|
91
93
|
|
92
94
|
##
|
93
95
|
# Fails unless +obj+ is empty.
|
94
96
|
|
95
97
|
def assert_empty obj, msg = nil
|
96
|
-
msg = message(msg) { "Expected #{obj
|
98
|
+
msg = message(msg) { "Expected #{mu_pp(obj)} to be empty" }
|
97
99
|
assert_respond_to obj, :empty?
|
98
100
|
assert obj.empty?, msg
|
99
101
|
end
|
@@ -243,8 +245,8 @@ module MiniTest
|
|
243
245
|
|
244
246
|
def assert_respond_to obj, meth, msg = nil
|
245
247
|
msg = message(msg) {
|
246
|
-
|
247
|
-
|
248
|
+
"Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
|
249
|
+
}
|
248
250
|
assert obj.respond_to?(meth), msg
|
249
251
|
end
|
250
252
|
|
@@ -506,27 +508,57 @@ module MiniTest
|
|
506
508
|
end
|
507
509
|
|
508
510
|
class Unit
|
509
|
-
VERSION = "
|
511
|
+
VERSION = "2.0.0" # :nodoc:
|
510
512
|
|
511
513
|
attr_accessor :report, :failures, :errors, :skips # :nodoc:
|
512
514
|
attr_accessor :test_count, :assertion_count # :nodoc:
|
513
515
|
attr_accessor :start_time # :nodoc:
|
516
|
+
attr_accessor :options # :nodoc:
|
517
|
+
attr_accessor :help # :nodoc:
|
518
|
+
attr_accessor :verbose # :nodoc:
|
514
519
|
|
515
520
|
@@installed_at_exit ||= false
|
516
521
|
@@out = $stdout
|
517
522
|
|
523
|
+
##
|
524
|
+
# A simple hook allowing you to run a block of code after the
|
525
|
+
# tests are done. Eg:
|
526
|
+
#
|
527
|
+
# MiniTest::Unit.after_tests { p $debugging_info }
|
528
|
+
|
529
|
+
def self.after_tests
|
530
|
+
at_exit { at_exit { yield } }
|
531
|
+
end
|
532
|
+
|
518
533
|
##
|
519
534
|
# Registers MiniTest::Unit to run tests at process exit
|
520
535
|
|
521
536
|
def self.autorun
|
522
537
|
at_exit {
|
523
538
|
next if $! # don't run if there was an exception
|
524
|
-
exit_code = MiniTest::Unit.new.run
|
539
|
+
exit_code = MiniTest::Unit.new.run ARGV
|
525
540
|
exit false if exit_code && exit_code != 0
|
526
541
|
} unless @@installed_at_exit
|
527
542
|
@@installed_at_exit = true
|
528
543
|
end
|
529
544
|
|
545
|
+
##
|
546
|
+
# Returns the stream to use for output.
|
547
|
+
|
548
|
+
def self.output
|
549
|
+
@@out
|
550
|
+
end
|
551
|
+
|
552
|
+
##
|
553
|
+
# Returns the stream to use for output.
|
554
|
+
#
|
555
|
+
# DEPRECATED: use ::output instead.
|
556
|
+
|
557
|
+
def self.out
|
558
|
+
warn "::out deprecated, use ::output instead." if $VERBOSE
|
559
|
+
output
|
560
|
+
end
|
561
|
+
|
530
562
|
##
|
531
563
|
# Sets MiniTest::Unit to write output to +stream+. $stdout is the default
|
532
564
|
# output
|
@@ -535,6 +567,93 @@ module MiniTest
|
|
535
567
|
@@out = stream
|
536
568
|
end
|
537
569
|
|
570
|
+
##
|
571
|
+
# Return all plugins' run methods (methods that start with "run_").
|
572
|
+
|
573
|
+
def self.plugins
|
574
|
+
@@plugins ||= (["run_tests"] +
|
575
|
+
public_instance_methods(false).
|
576
|
+
grep(/^run_/).map { |s| s.to_s }).uniq
|
577
|
+
end
|
578
|
+
|
579
|
+
def output
|
580
|
+
self.class.output
|
581
|
+
end
|
582
|
+
|
583
|
+
def puts *a # :nodoc:
|
584
|
+
output.puts(*a)
|
585
|
+
end
|
586
|
+
|
587
|
+
def print *a # :nodoc:
|
588
|
+
output.print(*a)
|
589
|
+
end
|
590
|
+
|
591
|
+
def _run_anything type
|
592
|
+
suites = TestCase.send "#{type}_suites"
|
593
|
+
return if suites.empty?
|
594
|
+
|
595
|
+
start = Time.now
|
596
|
+
|
597
|
+
puts
|
598
|
+
puts "# Running #{type}s:"
|
599
|
+
puts
|
600
|
+
|
601
|
+
@test_count, @assertion_count = 0, 0
|
602
|
+
sync = output.respond_to? :"sync=" # stupid emacs
|
603
|
+
old_sync, output.sync = output.sync, true if sync
|
604
|
+
|
605
|
+
results = _run_suites suites, type
|
606
|
+
|
607
|
+
@test_count = results.inject(0) { |sum, (tc, ac)| sum + tc }
|
608
|
+
@assertion_count = results.inject(0) { |sum, (tc, ac)| sum + ac }
|
609
|
+
|
610
|
+
output.sync = old_sync if sync
|
611
|
+
|
612
|
+
t = Time.now - start
|
613
|
+
|
614
|
+
puts
|
615
|
+
puts
|
616
|
+
puts "Finished #{type}s in %.6fs, %.4f tests/s, %.4f assertions/s." %
|
617
|
+
[t, test_count / t, assertion_count / t]
|
618
|
+
|
619
|
+
report.each_with_index do |msg, i|
|
620
|
+
puts "\n%3d) %s" % [i + 1, msg]
|
621
|
+
end
|
622
|
+
|
623
|
+
puts
|
624
|
+
|
625
|
+
status
|
626
|
+
end
|
627
|
+
|
628
|
+
def _run_suites suites, type
|
629
|
+
suites.map { |suite| _run_suite suite, type }
|
630
|
+
end
|
631
|
+
|
632
|
+
def _run_suite suite, type
|
633
|
+
header = "#{type}_suite_header"
|
634
|
+
puts send(header, suite) if respond_to? header
|
635
|
+
|
636
|
+
filter = options[:filter] || '/./'
|
637
|
+
filter = Regexp.new $1 if filter =~ /\/(.*)\//
|
638
|
+
|
639
|
+
assertions = suite.send("#{type}_methods").grep(filter).map { |method|
|
640
|
+
inst = suite.new method
|
641
|
+
inst._assertions = 0
|
642
|
+
|
643
|
+
start_time = Time.now
|
644
|
+
result = inst.run self
|
645
|
+
time = Time.now - start_time
|
646
|
+
|
647
|
+
print "#{suite}##{method} = %.2f s = " % time if @verbose
|
648
|
+
print result
|
649
|
+
puts if @verbose
|
650
|
+
|
651
|
+
inst._assertions
|
652
|
+
}
|
653
|
+
|
654
|
+
return assertions.size, assertions.inject(0) { |sum, n| sum + n }
|
655
|
+
end
|
656
|
+
|
538
657
|
def location e # :nodoc:
|
539
658
|
last_before_assertion = ""
|
540
659
|
e.backtrace.reverse_each do |s|
|
@@ -558,7 +677,7 @@ module MiniTest
|
|
558
677
|
"Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
|
559
678
|
else
|
560
679
|
@errors += 1
|
561
|
-
bt = MiniTest::filter_backtrace(e.backtrace).join
|
680
|
+
bt = MiniTest::filter_backtrace(e.backtrace).join "\n "
|
562
681
|
"Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n"
|
563
682
|
end
|
564
683
|
@report << e
|
@@ -573,6 +692,7 @@ module MiniTest
|
|
573
692
|
|
574
693
|
def process_args args = []
|
575
694
|
options = {}
|
695
|
+
orig_args = args.dup
|
576
696
|
|
577
697
|
OptionParser.new do |opts|
|
578
698
|
opts.banner = 'minitest options:'
|
@@ -595,9 +715,21 @@ module MiniTest
|
|
595
715
|
options[:filter] = a
|
596
716
|
end
|
597
717
|
|
598
|
-
opts.parse args
|
718
|
+
opts.parse! args
|
719
|
+
orig_args -= args
|
720
|
+
end
|
721
|
+
|
722
|
+
unless options[:seed] then
|
723
|
+
srand
|
724
|
+
options[:seed] = srand % 0xFFFF
|
725
|
+
orig_args << "--seed" << options[:seed].to_s
|
599
726
|
end
|
600
727
|
|
728
|
+
srand options[:seed]
|
729
|
+
|
730
|
+
self.verbose = options[:verbose]
|
731
|
+
@help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " "
|
732
|
+
|
601
733
|
options
|
602
734
|
end
|
603
735
|
|
@@ -605,89 +737,40 @@ module MiniTest
|
|
605
737
|
# Top level driver, controls all output and filtering.
|
606
738
|
|
607
739
|
def run args = []
|
608
|
-
options = process_args args
|
609
|
-
|
610
|
-
@verbose = options[:verbose]
|
740
|
+
self.options = process_args args
|
611
741
|
|
612
|
-
|
613
|
-
filter = Regexp.new $1 if filter and filter =~ /\/(.*)\//
|
742
|
+
puts "Run options: #{help}"
|
614
743
|
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
seed = srand % 0xFFFF
|
744
|
+
self.class.plugins.each do |plugin|
|
745
|
+
send plugin
|
746
|
+
break unless report.empty?
|
619
747
|
end
|
620
748
|
|
621
|
-
srand seed
|
622
|
-
|
623
|
-
help = ["--seed", seed]
|
624
|
-
help.push "--verbose" if @verbose
|
625
|
-
help.push("--name", options[:filter].inspect) if options[:filter]
|
626
|
-
|
627
|
-
@@out.puts "Test run options: #{help.join(" ")}"
|
628
|
-
@@out.puts
|
629
|
-
@@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
|
630
|
-
|
631
|
-
start = Time.now
|
632
|
-
run_test_suites filter
|
633
|
-
|
634
|
-
@@out.puts
|
635
|
-
@@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds."
|
636
|
-
|
637
|
-
@report.each_with_index do |msg, i|
|
638
|
-
@@out.puts "\n%3d) %s" % [i + 1, msg]
|
639
|
-
end
|
640
|
-
|
641
|
-
@@out.puts
|
642
|
-
|
643
|
-
status
|
644
|
-
|
645
|
-
@@out.puts
|
646
|
-
|
647
|
-
@@out.puts "Test run options: #{help.join(" ")}"
|
648
|
-
|
649
749
|
return failures + errors if @test_count > 0 # or return nil...
|
650
750
|
rescue Interrupt
|
651
751
|
abort 'Interrupted'
|
652
752
|
end
|
653
753
|
|
654
754
|
##
|
655
|
-
#
|
755
|
+
# Runs test suites matching +filter+.
|
656
756
|
|
657
|
-
def
|
658
|
-
|
659
|
-
io.puts format % [test_count, assertion_count, failures, errors, skips]
|
757
|
+
def run_tests
|
758
|
+
_run_anything :test
|
660
759
|
end
|
661
760
|
|
662
761
|
##
|
663
|
-
#
|
762
|
+
# Writes status to +io+
|
664
763
|
|
665
|
-
def
|
666
|
-
|
667
|
-
|
668
|
-
TestCase.test_suites.each do |suite|
|
669
|
-
suite.test_methods.grep(filter).each do |test|
|
670
|
-
inst = suite.new test
|
671
|
-
inst._assertions = 0
|
672
|
-
@@out.print "#{suite}##{test}: " if @verbose
|
673
|
-
|
674
|
-
@start_time = Time.now
|
675
|
-
result = inst.run(self)
|
676
|
-
|
677
|
-
@@out.print "%.2f s: " % (Time.now - @start_time) if @verbose
|
678
|
-
@@out.print result
|
679
|
-
@@out.puts if @verbose
|
680
|
-
@test_count += 1
|
681
|
-
@assertion_count += inst._assertions
|
682
|
-
end
|
683
|
-
end
|
684
|
-
@@out.sync = old_sync if @@out.respond_to? :sync=
|
685
|
-
[@test_count, @assertion_count]
|
764
|
+
def status io = self.output
|
765
|
+
format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
|
766
|
+
io.puts format % [test_count, assertion_count, failures, errors, skips]
|
686
767
|
end
|
687
768
|
|
688
769
|
##
|
689
|
-
# Subclass TestCase to create your own tests.
|
770
|
+
# Subclass TestCase to create your own tests. Typically you'll want a
|
690
771
|
# TestCase subclass per implementation class.
|
772
|
+
#
|
773
|
+
# See MiniTest::Assertions
|
691
774
|
|
692
775
|
class TestCase
|
693
776
|
attr_reader :__name__ # :nodoc:
|
@@ -701,30 +784,31 @@ module MiniTest
|
|
701
784
|
# Runs the tests reporting the status to +runner+
|
702
785
|
|
703
786
|
def run runner
|
704
|
-
trap
|
705
|
-
|
706
|
-
|
787
|
+
trap "INFO" do
|
788
|
+
time = Time.now - runner.start_time
|
789
|
+
warn "%s#%s %.2fs" % [self.class, self.__name__, time]
|
707
790
|
runner.status $stderr
|
708
791
|
end if SUPPORTS_INFO_SIGNAL
|
709
792
|
|
710
|
-
result =
|
793
|
+
result = ""
|
711
794
|
begin
|
712
795
|
@passed = nil
|
713
796
|
self.setup
|
714
797
|
self.__send__ self.__name__
|
798
|
+
result = "." unless io?
|
715
799
|
@passed = true
|
716
800
|
rescue *PASSTHROUGH_EXCEPTIONS
|
717
801
|
raise
|
718
802
|
rescue Exception => e
|
719
803
|
@passed = false
|
720
|
-
result = runner.puke
|
804
|
+
result = runner.puke self.class, self.__name__, e
|
721
805
|
ensure
|
722
806
|
begin
|
723
807
|
self.teardown
|
724
808
|
rescue *PASSTHROUGH_EXCEPTIONS
|
725
809
|
raise
|
726
810
|
rescue Exception => e
|
727
|
-
result = runner.puke
|
811
|
+
result = runner.puke self.class, self.__name__, e
|
728
812
|
end
|
729
813
|
trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL
|
730
814
|
end
|
@@ -733,9 +817,19 @@ module MiniTest
|
|
733
817
|
|
734
818
|
def initialize name # :nodoc:
|
735
819
|
@__name__ = name
|
820
|
+
@__io__ = nil
|
736
821
|
@passed = nil
|
737
822
|
end
|
738
823
|
|
824
|
+
def io
|
825
|
+
@__io__ = true
|
826
|
+
MiniTest::Unit.output
|
827
|
+
end
|
828
|
+
|
829
|
+
def io?
|
830
|
+
@__io__
|
831
|
+
end
|
832
|
+
|
739
833
|
def self.reset # :nodoc:
|
740
834
|
@@test_suites = {}
|
741
835
|
end
|
@@ -756,7 +850,7 @@ module MiniTest
|
|
756
850
|
end
|
757
851
|
|
758
852
|
def self.test_suites # :nodoc:
|
759
|
-
@@test_suites.keys.sort_by { |ts| ts.name }
|
853
|
+
@@test_suites.keys.sort_by { |ts| ts.name.to_s }
|
760
854
|
end
|
761
855
|
|
762
856
|
def self.test_methods # :nodoc:
|
@@ -765,7 +859,7 @@ module MiniTest
|
|
765
859
|
case self.test_order
|
766
860
|
when :random then
|
767
861
|
max = methods.size
|
768
|
-
methods.sort.sort_by { rand
|
862
|
+
methods.sort.sort_by { rand max }
|
769
863
|
when :alpha, :sorted then
|
770
864
|
methods.sort
|
771
865
|
else
|
@@ -807,4 +901,3 @@ if $DEBUG then
|
|
807
901
|
end
|
808
902
|
end
|
809
903
|
end
|
810
|
-
|