Welcome, guest | Sign In | My Account | Store | Cart

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, 80 lines
 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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

###############################################################################

class expected:

    def __init__(self, e):
        if isinstance(e, Exception):
            self._t, self._v = e.__class__, str(e)
        elif isinstance(e, type) and issubclass(e, Exception):
            self._t, self._v = e, None
        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 issubclass(t, self._t) and (self._v is None or str(v).startswith(self._v))

###############################################################################

if __name__ == "__main__": # some examples

    try:
        with expected("foo"):
            pass
    except Exception as e:
        assert str(e) == "usage: with expected(Exception): or with expected(Exception(\"text\"))", str(e)
    else:
        assert False

    with expected(ZeroDivisionError):
        1 / 0

    with expected(ZeroDivisionError("int division or modulo by zero")):
        1 / 0

    with expected(ZeroDivisionError("int division")):
        1 / 0

    try:
        with expected(ZeroDivisionError):
            1 / 2
    except AssertionError as e:
        assert str(e) == "expected ZeroDivisionError to have been thrown", str(e)
    else:
        assert False

    try:
        with expected(ZeroDivisionError("failure !!!")):
            1 / 0
    except ZeroDivisionError as e:
        assert str(e) == "int division or modulo by zero", str(e)
    else:
        assert False

    try:
        with expected(ZeroDivisionError):
            {}["foo"]
    except KeyError as e:
        assert str(e) == "'foo'", str(e)
    else:
        assert False

    with expected(KeyError):
        with expected(ZeroDivisionError):
            with expected(RuntimeError):
                {}["foo"]

    with expected(Exception("int division or modulo by zero")):
        1 / 0

    with expected(Exception):
        1 / 0

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>

Created by Dmitry Dvoinikov on Sat, 14 Jun 2008 (MIT)
Python recipes (4591)
Dmitry Dvoinikov's recipes (8)

Required Modules

  • (none specified)

Other Information and Tasks