Some time ago, I complained about assert_raise requiring one to list
specific exceptions in a test case. My issue is that I wanted to test
for the raising of a base exception OR any exception derived from that
base exception, because I did not want to have to change the unit tests
every time a different exception subclass is thrown by the method under
test or anything it calls.
I dynamically added a new assert function to Test::Unit, named
assert_raise_s, which works this way. It should not break any existing
Test::Unit functionality. At least one person emailed me and asked me to
provide the code for this function, so I am posting it here in case
others might want it, too. I think that Daniel Berger also talked about
needing something like this some time ago (he wasn't the person who
emailed me).
In your test case file(s), you just need to
require 'test/unit'
require 'assert_raise_s'
···
----
assert_raise_s.rb:
module Test
module Unit
module Assertions
private
def _expected_exception_or_subclass?(actual_exception, exceptions,
modules) # :nodoc:
exceptions.any? {|cls| actual_exception.class <= cls } or
modules.any? {|mod| actual_exception.is_a?(mod)}
end
##
# Passes if the block raises one of the given exceptions or its
descendants.
#
# Example:
# assert_raise_s RuntimeError, LoadError do
# raise 'Boom!!!'
# end
public
def assert_raise_s(*args)
_wrap_assertion do
if Module === args.last
message = ""
else
message = args.pop
end
exceptions, modules = _check_exception_class(args)
expected = args.size == 1 ? args.first : args
actual_exception = nil
full_message = build_message(message, "<?> exception expected
but none was thrown.", expected)
assert_block(full_message) do
begin
yield
rescue Exception => actual_exception
break
end
false
end
full_message = build_message(message, "<?> exception expected
but was\n?", expected, actual_exception)
assert_block(full_message)
{_expected_exception_or_subclass?(actual_exception, exceptions,
modules)}
actual_exception
end
end
end
end
end
--
Posted via http://www.ruby-forum.com/.