aboutsummaryrefslogtreecommitdiffstats
path: root/lib/minitest/unit.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/minitest/unit.rb')
-rw-r--r--lib/minitest/unit.rb217
1 files changed, 174 insertions, 43 deletions
diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb
index 2c767b68fa..0a0e10816e 100644
--- a/lib/minitest/unit.rb
+++ b/lib/minitest/unit.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
######################################################################
# This file is imported from the minitest project.
# DO NOT make modifications in this repo. They _will_ be reverted!
@@ -61,8 +62,13 @@ module MiniTest
# printed if the assertion fails.
module Assertions
+ UNDEFINED = Object.new # :nodoc:
- WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
+ def UNDEFINED.inspect # :nodoc:
+ "UNDEFINED" # again with the rdoc bugs... :(
+ end
+
+ WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ # :nodoc:
##
# Returns the diff command to use in #diff. Tries to intelligently
@@ -187,6 +193,7 @@ module MiniTest
# Fails unless the block returns a true value.
def assert_block msg = nil
+ warn "NOTE: MiniTest::Unit::TestCase#assert_block is deprecated, use assert. It will be removed on or after 2012-06-01."
msg = message(msg) { "Expected block to return true value" }
assert yield, msg
end
@@ -225,7 +232,7 @@ module MiniTest
def assert_in_delta exp, act, delta = 0.001, msg = nil
n = (exp - act).abs
- msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" }
+ msg = message(msg) { "Expected |#{exp} - #{act}| (#{n}) to be < #{delta}"}
assert delta >= n, msg
end
@@ -234,7 +241,7 @@ module MiniTest
# error less than +epsilon+.
def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
- assert_in_delta a, b, [a, b].min * epsilon, msg
+ assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg
end
##
@@ -270,13 +277,13 @@ module MiniTest
end
##
- # Fails unless +exp+ is <tt>=~</tt> +act+.
+ # Fails unless +matcher+ <tt>=~</tt> +obj+.
- def assert_match exp, act, msg = nil
- msg = message(msg) { "Expected #{mu_pp(exp)} to match #{mu_pp(act)}" }
- assert_respond_to act, :"=~"
- exp = Regexp.new Regexp.escape exp if String === exp and String === act
- assert exp =~ act, msg
+ def assert_match matcher, obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" }
+ assert_respond_to matcher, :"=~"
+ matcher = Regexp.new Regexp.escape matcher if String === matcher
+ assert matcher =~ obj, msg
end
##
@@ -287,9 +294,6 @@ module MiniTest
assert obj.nil?, msg
end
- UNDEFINED = Object.new
- def UNDEFINED.inspect; "UNDEFINED"; end
-
##
# For testing with binary operators.
#
@@ -313,8 +317,8 @@ module MiniTest
yield
end
- x = assert_equal stdout, out, "In stdout" if stdout
y = assert_equal stderr, err, "In stderr" if stderr
+ x = assert_equal stdout, out, "In stdout" if stdout
(!stdout || x) && (!stderr || y)
end
@@ -334,10 +338,11 @@ module MiniTest
end
##
- # Fails unless the block raises one of +exp+
+ # Fails unless the block raises one of +exp+. Returns the
+ # exception matched so you can check the message, attributes, etc.
def assert_raises *exp
- msg = "#{exp.pop}\n" if String === exp.last
+ msg = "#{exp.pop}.\n" if String === exp.last
should_raise = false
begin
@@ -355,7 +360,7 @@ module MiniTest
details = "#{msg}#{mu_pp(exp)} exception expected, not"
assert(exp.any? { |ex|
ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class
- }, proc{exception_details(e, details)})
+ }, exception_details(e, details))
return e
end
@@ -523,14 +528,14 @@ module MiniTest
end
##
- # For comparing Floats. Fails if +exp+ is within +delta+ of +act+
+ # For comparing Floats. Fails if +exp+ is within +delta+ of +act+.
#
# refute_in_delta Math::PI, (22.0 / 7.0)
def refute_in_delta exp, act, delta = 0.001, msg = nil
n = (exp - act).abs
msg = message(msg) {
- "Expected #{exp} - #{act} (#{n}) to not be < #{delta}"
+ "Expected |#{exp} - #{act}| (#{n}) to not be < #{delta}"
}
refute delta > n, msg
end
@@ -544,7 +549,7 @@ module MiniTest
end
##
- # Fails if +collection+ includes +obj+
+ # Fails if +collection+ includes +obj+.
def refute_includes collection, obj, msg = nil
msg = message(msg) {
@@ -555,7 +560,7 @@ module MiniTest
end
##
- # Fails if +obj+ is an instance of +cls+
+ # Fails if +obj+ is an instance of +cls+.
def refute_instance_of cls, obj, msg = nil
msg = message(msg) {
@@ -565,7 +570,7 @@ module MiniTest
end
##
- # Fails if +obj+ is a kind of +cls+
+ # Fails if +obj+ is a kind of +cls+.
def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
@@ -573,13 +578,13 @@ module MiniTest
end
##
- # Fails if +exp+ <tt>=~</tt> +act+
+ # Fails if +matcher+ <tt>=~</tt> +obj+.
- def refute_match exp, act, msg = nil
- msg = message(msg) { "Expected #{mu_pp(exp)} to not match #{mu_pp(act)}" }
- assert_respond_to act, :"=~"
- exp = (/#{Regexp.escape exp}/) if String === exp and String === act
- refute exp =~ act, msg
+ def refute_match matcher, obj, msg = nil
+ msg = message(msg) {"Expected #{mu_pp matcher} to not match #{mu_pp obj}"}
+ assert_respond_to matcher, :"=~"
+ matcher = Regexp.new Regexp.escape matcher if String === matcher
+ refute matcher =~ obj, msg
end
##
@@ -646,8 +651,8 @@ module MiniTest
end
end
- class Unit
- VERSION = "2.8.1" # :nodoc:
+ class Unit # :nodoc:
+ VERSION = "2.12.1" # :nodoc:
attr_accessor :report, :failures, :errors, :skips # :nodoc:
attr_accessor :test_count, :assertion_count # :nodoc:
@@ -655,6 +660,10 @@ module MiniTest
attr_accessor :help # :nodoc:
attr_accessor :verbose # :nodoc:
attr_writer :options # :nodoc:
+ attr_accessor :last_error # :nodoc:
+
+ ##
+ # Lazy accessor for options.
def options
@options ||= {}
@@ -662,6 +671,7 @@ module MiniTest
@@installed_at_exit ||= false
@@out = $stdout
+ @@after_tests = []
##
# A simple hook allowing you to run a block of code after the
@@ -669,8 +679,8 @@ module MiniTest
#
# MiniTest::Unit.after_tests { p $debugging_info }
- def self.after_tests
- at_exit { at_exit { yield } }
+ def self.after_tests &block
+ @@after_tests << block
end
##
@@ -686,7 +696,10 @@ module MiniTest
# to run (at_exit stacks).
exit_code = nil
- at_exit { exit false if exit_code && exit_code != 0 }
+ at_exit {
+ @@after_tests.reverse_each(&:call)
+ exit false if exit_code && exit_code != 0
+ }
exit_code = MiniTest::Unit.new.run ARGV
} unless @@installed_at_exit
@@ -744,6 +757,9 @@ module MiniTest
grep(/^run_/).map { |s| s.to_s }).uniq
end
+ ##
+ # Return the IO for output.
+
def output
self.class.output
end
@@ -756,6 +772,9 @@ module MiniTest
output.print(*a)
end
+ ##
+ # Runner for a given +type+ (eg, test vs bench).
+
def _run_anything type
suites = TestCase.send "#{type}_suites"
return if suites.empty?
@@ -793,10 +812,16 @@ module MiniTest
status
end
+ ##
+ # Runs all the +suites+ for a given +type+.
+
def _run_suites suites, type
suites.map { |suite| _run_suite suite, type }
end
+ ##
+ # Run a single +suite+ for a given +type+.
+
def _run_suite suite, type
header = "#{type}_suite_header"
puts send(header, suite) if respond_to? header
@@ -811,9 +836,12 @@ module MiniTest
print "#{suite}##{method} = " if @verbose
@start_time = Time.now
+ self.last_error = nil
result = inst.run self
time = Time.now - @start_time
+ record suite, method, inst._assertions, time, last_error
+
print "%.2f s = " % time if @verbose
print result
puts if @verbose
@@ -824,6 +852,21 @@ module MiniTest
return assertions.size, assertions.inject(0) { |sum, n| sum + n }
end
+ ##
+ # Record the result of a single run. Makes it very easy to gather
+ # information. Eg:
+ #
+ # class StatisticsRecorder < MiniTest::Unit
+ # def record suite, method, assertions, time, error
+ # # ... record the results somewhere ...
+ # end
+ # end
+ #
+ # MiniTest::Unit.runner = StatisticsRecorder.new
+
+ def record suite, method, assertions, time, error
+ end
+
def location e # :nodoc:
last_before_assertion = ""
e.backtrace.reverse_each do |s|
@@ -838,6 +881,7 @@ module MiniTest
# exception +e+
def puke klass, meth, e
+ self.last_error = e
e = case e
when MiniTest::Skip then
@skips += 1
@@ -859,9 +903,10 @@ module MiniTest
@report = []
@errors = @failures = @skips = 0
@verbose = false
+ self.last_error = nil
end
- def process_args args = []
+ def process_args args = [] # :nodoc:
options = {}
orig_args = args.dup
@@ -882,7 +927,7 @@ module MiniTest
options[:verbose] = true
end
- opts.on '-n', '--name PATTERN', "Filter test names on pattern." do |a|
+ opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |a|
options[:filter] = a
end
@@ -945,12 +990,61 @@ module MiniTest
end
##
+ # Provides a simple set of guards that you can use in your tests
+ # to skip execution if it is not applicable. These methods are
+ # mixed into TestCase as both instance and class methods so you
+ # can use them inside or outside of the test methods.
+ #
+ # def test_something_for_mri
+ # skip "bug 1234" if jruby?
+ # # ...
+ # end
+ #
+ # if windows? then
+ # # ... lots of test methods ...
+ # end
+
+ module Guard
+
+ ##
+ # Is this running on jruby?
+
+ def jruby? platform = RUBY_PLATFORM
+ "java" == platform
+ end
+
+ ##
+ # Is this running on mri?
+
+ def mri? platform = RUBY_DESCRIPTION
+ /^ruby/ =~ platform
+ end
+
+ ##
+ # Is this running on rubinius?
+
+ def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
+ "rbx" == platform
+ end
+
+ ##
+ # Is this running on windows?
+
+ def windows? platform = RUBY_PLATFORM
+ /mswin|mingw/ =~ platform
+ end
+ end
+
+ ##
# Subclass TestCase to create your own tests. Typically you'll want a
# TestCase subclass per implementation class.
#
# See MiniTest::Assertions
class TestCase
+ include Guard
+ extend Guard
+
attr_reader :__name__ # :nodoc:
PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException,
@@ -963,16 +1057,21 @@ module MiniTest
def run runner
trap "INFO" do
+ runner.report.each_with_index do |msg, i|
+ warn "\n%3d) %s" % [i + 1, msg]
+ end
+ warn ''
time = runner.start_time ? Time.now - runner.start_time : 0
- warn "%s#%s %.2fs" % [self.class, self.__name__, time]
+ warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time]
runner.status $stderr
end if SUPPORTS_INFO_SIGNAL
result = ""
begin
@passed = nil
+ self.before_setup
self.setup
- self.run_setup_hooks
+ self.after_setup
self.run_test self.__name__
result = "." unless io?
@passed = true
@@ -982,13 +1081,14 @@ module MiniTest
@passed = false
result = runner.puke self.class, self.__name__, e
ensure
- begin
- self.run_teardown_hooks
- self.teardown
- rescue *PASSTHROUGH_EXCEPTIONS
- raise
- rescue Exception => e
- result = runner.puke self.class, self.__name__, e
+ %w{ before_teardown teardown after_teardown }.each do |hook|
+ begin
+ self.send hook
+ rescue *PASSTHROUGH_EXCEPTIONS
+ raise
+ rescue Exception => e
+ result = runner.puke self.class, self.__name__, e
+ end
end
trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL
end
@@ -1008,11 +1108,17 @@ module MiniTest
@@current
end
+ ##
+ # Return the output IO object
+
def io
@__io__ = true
MiniTest::Unit.output
end
+ ##
+ # Have we hooked up the IO yet?
+
def io?
@__io__
end
@@ -1030,6 +1136,7 @@ module MiniTest
def self.i_suck_and_my_tests_are_order_dependent!
class << self
+ undef_method :test_order if method_defined? :test_order
define_method :test_order do :alpha end
end
end
@@ -1075,10 +1182,32 @@ module MiniTest
def setup; end
##
+ # Runs before every test after setup. Use this to refactor test
+ # initialization.
+
+ def after_setup; end
+
+ ##
+ # Runs before every setup. Use this to refactor test initialization.
+
+ def before_setup; end
+
+ ##
# Runs after every test. Use this to refactor test cleanup.
def teardown; end
+ ##
+ # Runs after every test before teardown. Use this to refactor test
+ # initialization.
+
+ def before_teardown; end
+
+ ##
+ # Runs after every teardown. Use this to refactor test cleanup.
+
+ def after_teardown; end
+
def self.reset_setup_teardown_hooks # :nodoc:
@setup_hooks = []
@teardown_hooks = []
@@ -1189,6 +1318,8 @@ module MiniTest
end # class Unit
end # module MiniTest
+Minitest = MiniTest # because ugh... I typo this all the time
+
if $DEBUG then
module Test # :nodoc:
module Unit # :nodoc: