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