Monday, July 16, 2007

assert_interface

I've been reading quite a bit on programming these days. And one of the things I'm liking more and more is the concept of programming for the interface.
Now I use Ruby and not Java or C# or other languages, so the idea of the interface is a bit different. I can implement them, kind of, via a module.
However, I want to make sure that my objects quack appropriately. Enter assert_interface(object, module). The object is assumed to be an
instance of a class. The module is assumed to be "well-formed" for interfaces

module WellFormedInterface
def self.included(base)
base.send(:include, InstanceMethods)
base.extend(ClassMethods)
end

module ClassMethods
end
module InstanceMethods
end
end

class AbstractUnit
include WellFormedInterface
end




class Test::Unit::TestCase
# Given an object (i.e. Foo.new), and a module (i.e. SomethingCool)
# assert that all methods explicitly defined in the module
# are present in the object.
#
# This isn't the end all test, as you are still responsible for
# testing the implementation of the interface
def assert_interface(object, mod)
methods = {object => [], object.class => []}

mod::InstanceMethods.instance_methods(false).each do |method|
methods[object] << method unless object.respond_to?(method)
end

mod::ClassMethods.instance_methods(false).each do |method|
methods[object.class] << method unless object.class.respond_to?(method)
end

msg = []
methods.each_pair do |key, value|
msg << "Expected #{key} to respond to the following :#{value.join(' :')}" unless value.empty?
end

if msg.empty?
assert true, 'Hey, it all worked'
else
flunk msg.join('. ')
end
end
end

No comments: