I want to write a test to establish that an Exception is not raised in a given circumstance.
It\'s straightforward to test if an Exception is raise
You can define assertNotRaises
by reusing about 90% of the original implementation of assertRaises
in the unittest
module. With this approach, you end up with an assertNotRaises
method that, aside from its reversed failure condition, behaves identically to assertRaises
.
It turns out to be surprisingly easy to add an assertNotRaises
method to unittest.TestCase
(it took me about 4 times as long to write this answer as it did the code). Here's a live demo of the assertNotRaises method in action. Just like assertRaises, you can either pass a callable and args to assertNotRaises
, or you can use it in a with
statement. The live demo includes a test cases that demonstrates that assertNotRaises
works as intended.
The implementation of assertRaises
in unittest
is fairly complicated, but with a little bit of clever subclassing you can override and reverse its failure condition.
assertRaises
is a short method that basically just creates an instance of the unittest.case._AssertRaisesContext
class and returns it (see its definition in the unittest.case
module). You can define your own _AssertNotRaisesContext
class by subclassing _AssertRaisesContext
and overriding its __exit__
method:
import traceback
from unittest.case import _AssertRaisesContext
class _AssertNotRaisesContext(_AssertRaisesContext):
def __exit__(self, exc_type, exc_value, tb):
if exc_type is not None:
self.exception = exc_value.with_traceback(None)
try:
exc_name = self.expected.__name__
except AttributeError:
exc_name = str(self.expected)
if self.obj_name:
self._raiseFailure("{} raised by {}".format(exc_name,
self.obj_name))
else:
self._raiseFailure("{} raised".format(exc_name))
else:
traceback.clear_frames(tb)
return True
Normally you define test case classes by having them inherit from TestCase
. If you instead inherit from a subclass MyTestCase
:
class MyTestCase(unittest.TestCase):
def assertNotRaises(self, expected_exception, *args, **kwargs):
context = _AssertNotRaisesContext(expected_exception, self)
try:
return context.handle('assertNotRaises', args, kwargs)
finally:
context = None
all of your test cases will now have the assertNotRaises
method available to them.