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/.