unittest: assertRaises() with an instance instead of a type

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Mar 28 20:07:01 CEST 2012


On Wed, 28 Mar 2012 14:28:08 +0200, Ulrich Eckhardt wrote:

> Hi!
> 
> I'm currently writing some tests for the error handling of some code. In
> this scenario, I must make sure that both the correct exception is
> raised and that the contained error code is correct:
> 
> 
>    try:
>        foo()
>        self.fail('exception not raised')
>    catch MyException as e:
>        self.assertEqual(e.errorcode, SOME_FOO_ERROR)
>    catch Exception:
>        self.fail('unexpected exception raised')

First off, that is not Python code. "catch Exception" gives a syntax 
error.

Secondly, that is not the right way to do this unit test. You are testing 
two distinct things, so you should write it as two separate tests:


    def testFooRaisesException(self):
        # Test that foo() raises an exception.
        self.assertRaises(MyException, foo)


If foo does *not* raise an exception, the unittest framework will handle 
the failure for you. If it raises a different exception, the framework 
will also handle that too.

Then write a second test to check the exception code:

    def testFooExceptionCode(self):
        # Test that foo()'s exception has the right error code.
        try:
            foo()
        except MyException as err:
            self.assertEquals(err.errorcode, SOME_FOO_ERROR)
        

Again, let the framework handle any unexpected cases.

If you have lots of functions to test, write a helper function:

def catch(exception, func, *args, **kwargs):
    try:
        func(*args, **kwargs)
    except exception as err:
        return err
    raise RuntimeError('no error raised')


and then the test becomes:

    def testFooExceptionCode(self):
        # Test that foo()'s exception has the right error code.
        self.assertEquals(
            catch(MyException, foo).errorcode, SOME_FOO_ERROR
            )



(By the way, I have to question the design of an exception with error 
codes. That seems pretty poor design to me. Normally the exception *type* 
acts as equivalent to an error code.)


-- 
Steven



More information about the Python-list mailing list