Introducing: MicroTest
Posted by Mathew Abonyi Wed, 10 Jan 2007 21:04:32 GMT
Something I cooked up in an hour for bootstrap testing a testing framework.
If anyone actually wants me to maintain it, just give a shout and I’ll gemify it.
# A super-small testing suite.
# Just two ways to assert:
# expect { (whatever must return true) }
# do_not_expect { (whatever must return false) }
#
# A microtest looks like this:
#
# class BinaryMicroTest < MicroTest
# def should_exit_cleanly
# expect do
# `ruby #{myexec}`
# $? == 0
# end
# end
# end
#
class MicroTest
class MicroFailure < StandardError; end
class << self
attr_accessor :passed, :failed, :executed, :expectations, :planned, :plan, :failures
def run
init
execute
report
end
def init
self.passed, self.failed, self.executed, self.expectations = 0, 0, 0, 0
self.planned, self.plan = harvest
self.failures = []
end
def harvest
plan = []
ObjectSpace.each_object(Class) do |k|
if k.respond_to?(:superclass) && k.superclass == MicroTest
plan << [k, k.instance_methods.grep(/^should_/)]
end
end
planned = plan.inject(0) { |c, ary| c += ary[1].size; c }
[planned, plan]
end
def execute
puts "Running #{self.planned} test(s)..."
self.plan.each do |klass, tests|
tests.each do |test|
instance = klass.new
r = catch_failures(klass, test) { instance.send(test) }
if r
self.passed += 1
print "."
STDOUT.flush
else
self.failed += 1
print "F"
STDOUT.flush
end
self.expectations += instance.expectation_count
self.executed += 1
end
end
end
def catch_failures(klass, test)
begin
yield
true
rescue Exception => e
self.failures << [klass, test, e]
false
end
end
def report
puts "\n\n"
puts "%d planned, %d executed, %d passed, %d failed.\n%d expectations found." %
[self.planned, self.executed, self.passed, self.failed, self.expectations]
unless self.failures.empty?
puts "\nFAILURE REPORT\n"
self.failures.each { |f| report_failure(f) }
end
end
def report_failure(f)
puts "Suite: #{f[0]}\nTest: #{f[1]}\nException: #{f[2].class}\nMessage: #{f[2].message}"
puts ("\t" << f[2].backtrace.join("\n\t"))
end
end
attr_accessor :expectation_count
def initialize
self.expectation_count = 0
end
def expect(&block)
self.expectation_count += 1
raise MicroFailure, "should be true" unless block.call
end
def do_not_expect(&block)
self.expectation_count += 1
raise MicroFailure, "should be false" if block.call
end
end
at_exit do
MicroTest.run
end
Just dump that in a helper file and require it, as per normal Test::Unit practices.

hi all.