This morning I spent a happy hour exploring a little of ruby's Test::Unit::TestCase.
I started with this:
require 'test/unit'
class MyTest < Test::Unit::TestCase
def test_one_plus_one_equals_two
assert_equal 2, 1+1.1
end
end
I wanted to see how little I needed to write my own,
super-minimal implementation of Test::Unit::TestCase...
require 'test/unit'
class MyTest < MyTestCase
def test_one_plus_one_equals_two
assert_equal 2, 1+1.1
end
end
After 204 traffic lights in
cyber-dojo I ended up with this...
require 'assertion_failed_error'
class MyTestCase
def self.test_names
public_instance_methods.select{|name| name =~ /^test_/}
end
def assert_equal( expected, actual )
message =
"#{expected.inspect} expected but was\n" +
"#{actual.inspect}\n"
assert_block(message) { expected == actual }
end
def assert_block( message )
if (! yield)
raise AssertionFailedError.new(message.to_s)
end
end
end
at_exit do
::ObjectSpace.each_object(Class) do |klass|
if (klass < MyTestCase)
klass.test_names.each do |method_name|
begin
klass.new.send method_name
rescue AssertionFailedError => error
print "#{klass.name}:#{method_name}:\n" +
"#{error.message}"
end
end
end
end
end
class AssertionFailedError < RuntimeError; end
which allowed me write...
require 'my_test_case'
class MyTest < MyTestCase
def test_one_plus_one_equals_two
assert_equal 2, 1+1.1
end
end
and finally, I added this...
class MyTestCase
...
def self.test( name, &block )
define_method("test_#{name}".to_sym, &block)
end
...
end
which allowed me to rewrite the test as...
require 'my_test_case'
class MyTest < MyTestCase
test "1+1 == 2" do
assert_equal 2, 1+1.1
end
end
Fun :-)