Created
December 25, 2008 16:36
-
-
Save Sixeight/39915 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is a test/unit clone which was written to practice. | |
# | |
# Usage: | |
# | |
# require 'simpletest' | |
# | |
# class Foo < SimpleTest::TestCase | |
# | |
# def test_bar | |
# assert_equal 1, 1 | |
# end | |
# end | |
# | |
# Original: | |
# verbose_on, delta_is, assert_ | |
# | |
module SimpleTest | |
class Failed < StandardError; end | |
class Pended < StandardError; end | |
def self.backtrace(bt) | |
bt.select {|line| line !~ /#{__FILE__}/ } | |
end | |
module Assertions | |
def assert(test, msg = nil) | |
unless test | |
unless msg.instance_of?(Proc) | |
msg = message(msg) { | |
" expected true, got false\n\n" | |
} | |
end | |
raise Failed, msg.call | |
end | |
self.assertions += 1 | |
true | |
end | |
def assert_block(msg = 'assert_block failed', &block) | |
assert block.call, message(msg) | |
end | |
def assert_equal(expected, actual, msg = nil) | |
msg = message(msg) { | |
" expected <#{expected}> but\n" + | |
" got <#{actual}>\n\n" | |
} | |
assert expected == actual, msg | |
end | |
def assert_in_delta(expected, actual, delta = TestCase.delta, msg = nil) | |
msg = message(msg) { | |
" expected <#{expected}> +/- (< #{delta}) but\n" + | |
" got <#{actual}>\n\n" | |
} | |
difference = (expected.to_f - actual.to_f).abs | |
assert difference <= delta.to_f, msg | |
end | |
def assert_instance_of(obj, klass, msg = nil) | |
msg = message(msg) { | |
" expected <#{obj.inspect}> is instance of <#{klass}>\n\n" | |
} | |
assert obj.instance_of?(klass), msg | |
end | |
def assert_kind_of(obj, klass, msg = nil) | |
msg = message(msg) { | |
" expected <#{obj.inspect}> is kind of <#{klass}>\n\n" | |
} | |
assert obj.kind_of?(klass), msg | |
end | |
def assert_match(regexp, string, msg = nil) | |
fold = string.length > 20 | |
msg = message(msg) { | |
" expected <#{string.inspect}>" + | |
(fold ? "\n " : ' ') + | |
"to match <#{regexp.inspect}>\n\n" | |
} | |
regexp = /#{regexp}/ unless regexp.instance_of?(Regexp) | |
assert regexp =~ string, msg | |
end | |
def assert_respond_to(obj, message, msg = nil) | |
msg = message(msg) { | |
" expected <#{obj.inspect}> to respond to <:#{message}>\n\n" | |
} | |
assert obj.respond_to?(message), msg | |
end | |
def assert_nil(object, msg = 'assert_nil failed') | |
assert object.nil?, message(msg) | |
end | |
def assert_same(expected, actual, msg = nil) | |
msg = message(msg) { | |
" expected <#{expected}> but\n" + | |
" got <#{actual}> (using equal?)\n\n" | |
} | |
assert expected.equal?(actual), message(msg) | |
end | |
def assert_send(send_array, msg = nil) | |
obj = send_array.shift | |
meth = send_array.shift | |
msg = message(msg) { | |
" expected <#{obj.inspect}> #{meth} <[#{send_array * ','}]> but not\n\n" | |
} | |
assert obj.__send__(meth, *send_array), message(msg) | |
rescue | |
assert false, message(msg) | |
end | |
def assert_throws(expected_symbol = nil, msg = nil, &block) | |
thrown = true | |
catch(expected_symbol || :" __ dummy symbol __ ") do | |
begin | |
block.call | |
rescue => e | |
msg = message(msg) { | |
"expected <:#{expected_symbol}> but\n" + | |
" got <#{e.name}> was thrown" | |
} | |
thrown = false if expected_symbol | |
else | |
msg = message(msg) { | |
" expected <:#{expected_symbol or 'Symbol'}> but nothing was thrown\n\n" | |
} | |
thrown = false | |
end | |
end | |
assert thrown, message(msg) | |
end | |
def assert_operator(obj1, operator, obj2, msg = nil) | |
msg = message(msg) { | |
" expected <#{obj1.inspect}> #{operator} <#{obj2.inspect}> but not\n\n" | |
} | |
assert obj1.__send__(operator, obj2), message(msg) | |
rescue | |
assert false, message(msg) | |
end | |
def assert_raise(*klass, &block) | |
msg = nil | |
msg = klass.pop if klass[-1].instance_of?(String) | |
raised = false | |
begin | |
block.call | |
rescue => e | |
if klass.include?(e.class) | |
raised = true | |
else | |
msg = message(msg) { | |
" expected <#{klass * ','}> but\n" + | |
" got <#{e.class}>\n" + | |
" with #{e.message.inspect}\n\n" + | |
" -----\n" + | |
" #{SimpleTest.backtrace(e.backtrace).join("\n ")}\n\n" | |
} | |
end | |
else | |
msg = message(msg) { | |
" expedted <#{klass * ','}> but nothing raised\n\n" | |
} | |
end | |
assert raised, message(msg) | |
end | |
alias assert_raises assert_raise | |
def assert_not(test, msg = nil) | |
msg = message(msg) { | |
" expected 'not' true, got true\n\n" | |
} | |
assert !test, message(msg) | |
end | |
def assert_no_match(regexp, string, msg = nil) | |
fold = string.length > 20 | |
msg = message(msg) { | |
" expected <#{string.inspect}>" + | |
(fold ? "\n " : ' ') + | |
"'not' to match <#{regexp.inspect}>\n\n" | |
} | |
regexp = /#{regexp}/ unless regexp.instance_of?(Regexp) | |
assert regexp !~ string, message(msg) | |
end | |
def assert_not_equal(expected, actual, msg = nil) | |
msg = message(msg) { | |
" expected <#{expected}> 'not' equal <#{actual}>\n\n" | |
} | |
assert expected != actual, message(msg) | |
end | |
def assert_not_nil(object, msg = nil) | |
msg = message(msg) { | |
" expected <#{object.inspect}> 'not' nil\n\n" | |
} | |
assert !object.nil?, msg | |
end | |
def assert_not_same(expected, actual, msg = nil) | |
msg = message(msg) { | |
" expected <#{expected.inspect}>\n" + | |
" 'not' same as <#{actual.inspect}>\n\n" | |
} | |
assert !expected.equal?(actual), msg | |
end | |
def assert_nothing_raised(msg = nil, &block) | |
raised = false | |
begin | |
block.call | |
rescue => e | |
raised = true | |
msg = message(msg) { | |
" expected no Exception but\n" + | |
" got <#{e.class}>\n\n" | |
} | |
end | |
assert !raised, msg | |
end | |
def assert_nothing_thrown(msg = nil, &block) | |
thrown = false | |
begin | |
block.call | |
rescue => e | |
raise e unless /uncaught throw `(.*)'/ =~ e.message | |
thrown = true | |
msg = message(msg) { | |
" expected nothing was thrown but\n" + | |
" got <:#{$1}>\n\n" | |
} | |
end | |
assert !thrown, msg | |
end | |
def flunk(reason = 'Flunked!') | |
assert false, message(reason) | |
end | |
def pending(reason = nil) | |
raise Pended, message(reason).call | |
end | |
def assertions=(val) | |
@_assertions = val | |
end | |
def assertions | |
@_assertions ||= 0 | |
end | |
def message(memo = nil, &message) | |
lambda { | |
msg = SimpleTest.backtrace(caller)[0].sub(/in.*\z/, '') | |
msg += "\n\n" | |
msg += "#{message.call}" if message | |
msg += (memo ? " #{memo.inspect}" : ' ') | |
} | |
end | |
end | |
module Utilities | |
def delta_is(delta) | |
@@_default_delta = delta | |
end | |
def delta | |
@@_default_delta ||= 0.001 | |
end | |
def verbose_on | |
@@_verbose = true | |
end | |
def verbose? | |
@@_verbose ||= false | |
end | |
def assert_(name, &block) | |
define_method "assert_#{name}", &block | |
end | |
end | |
class TestSuite | |
@@_install = false | |
def self.autorun | |
at_exit { | |
run | |
@@_install = true | |
} unless installed? | |
end | |
def self.installed?; @@_install end | |
def self.run | |
puts "Loaded suite #{TestCase.test_files}" | |
puts 'Started' | |
start = Time.now | |
messages = '' | |
mark = ' ' | |
list = [] | |
counter = { | |
:passed => 0, | |
:failed => 0, | |
:error => 0, | |
:pended => 0, | |
} | |
# TODO: this proc needs to become method | |
format_result = lambda {|type, msg, test_case, meth| | |
counter[type] += 1 | |
count = counter.values_at(:failed, :error, :pended).inject(0, :+) | |
messages << format(msg) % [count, type.to_s.capitalize, test_case.class, meth] | |
print mark = type.to_s[0, 1].upcase | |
} | |
TestCase.test_suite.each do |test_case| | |
test_case = test_case.new | |
test_case.setup | |
test_case.class.test_methods.each do |meth| | |
start_assertion = Time.now | |
begin | |
test_case.__send__ meth | |
rescue Failed => msg | |
format_result[:failed, msg, test_case, meth] | |
rescue Pended => msg | |
format_result[:pended, msg, test_case, meth] | |
rescue => msg | |
msg = test_case.message(msg).call | |
format_result[:error, msg, test_case, meth] | |
else | |
print mark = '.' | |
end | |
time = Time.now - start_assertion | |
list << ["#{mark}) #{test_case.class}##{meth} ", time] | |
end | |
counter[:passed] += test_case.assertions | |
test_case.teardown | |
end | |
puts | |
puts test_list(list).unshift("\n") if TestCase.verbose? | |
puts | |
puts messages unless messages.empty? | |
puts | |
puts "Finished in %f seconds" % (Time.now - start) | |
puts | |
puts "%d passed, %d failed, %d errors, %d pended" % | |
counter.values_at(:passed, :failed, :errors, :pended) | |
end | |
def self.test_list(list) | |
width = list.max_by {|test, _| test.length }.first.length | |
list.map do |test, time| | |
test.ljust(width) + "(%f)" % time | |
end | |
end | |
def self.format(msg) | |
fold = msg.to_s.split("\n")[-1].length > 20 | |
"%d)\n" + | |
"%s: #{msg}" + | |
(fold ? "\n - " : ' ') + | |
"in %s#%s\n\n" | |
end | |
end | |
class TestCase | |
@@_test_suite = [] | |
@@_test_files = [] | |
def self.method_added(meth) | |
if meth.to_s =~ /\Atest_/ | |
methods = self.test_methods | |
warn "Warn: #{meth} has over writed\n" if methods.include? meth | |
methods = self.test_methods | [meth] | |
metaclass = class << self; self end | |
metaclass.__send__ :define_method, :test_methods, lambda { methods } | |
end | |
end | |
def self.inherited(klass) | |
@@_test_suite << klass | |
@@_test_files |= [$0] | |
TestSuite.autorun | |
end | |
def self.test_methods; [] end | |
def self.test_suite; @@_test_suite end | |
def self.test_files; @@_test_files end | |
def setup; end | |
def teardown; end | |
include Assertions | |
extend Utilities | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment