ActiveState Code

Recipe 573452: Assertion that a code fragment throws a particular exception (self-test utility, Python 3000)


The class presented in this recipe is useful when you are writing module self-tests and need to assert that a fragment of code throws a particular exception.

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class expected:

    def __init__(self, e):
        if isinstance(e, Exception):
            self._t, self._v = e.__class__, str(e)
        elif isinstance(e, type):
            self._t, self._v = e, ""
        else:
            raise Exception("usage: with expected(Exception): ... or "
                            "with expected(Exception(\"text\")): ...")

    def __enter__(self):
        try:
            pass
        except:
            pass # this is a Python 3000 way of saying sys.exc_clear()

    def __exit__(self, t, v, tb):
        assert t is not None, "expected {0:s} to have been thrown".format(self._t.__name__)
        return t is self._t and str(v).startswith(self._v)

if __name__ == "__main__": # some examples

    with expected(ZeroDivisionError):
        1 / 0

    with expected(AssertionError("expected ZeroDivisionError to have been thrown")):
        with expected(ZeroDivisionError):
            1 / 2

    with expected(Exception("foo")):
        raise Exception("foo")

    with expected(Exception("bar")):
        with expected(Exception("foo")): # this won't catch it
            raise Exception("bar")
        assert False, "should not see me"

    with expected(Exception("can specify")):
        raise Exception("can specify prefixes")

Discussion

I previously had to write something like

<pre> try: ... tested code ... except SomeException, e: assert str(e).startswith("expected error") else: assert False, "should have thrown" </pre> which was really cumbersome. Now I simply do <pre> with expected(SomeException("expected error")): ... tested code ... </pre>

Sign in to comment