Możesz zdefiniować assertNotRaises
, ponownie wykorzystując około 90% oryginalnej implementacji assertRaises
w unittest
module. Dzięki takiemu podejściu uzyskuje się assertNotRaises
metodę, która oprócz odwróconego stanu awarii zachowuje się identycznie assertRaises
.
TLDR i demo na żywo
Okazuje się, że dodanie assertNotRaises
metody jest zaskakująco łatwe unittest.TestCase
(napisanie tej odpowiedzi zajęło mi około 4 razy więcej czasu niż kodu). Oto demo na żywo assertNotRaises
metody w akcji . Tylko jakassertRaises
, można przejść wywoływalnym i args się assertNotRaises
, czy można go używać w with
oświadczeniu. Demo na żywo zawiera przypadki testowe, które pokazują, że assertNotRaises
działa zgodnie z przeznaczeniem.
Detale
Realizacja assertRaises
wunittest
jest dość skomplikowana, ale przy odrobinie sprytnej podklasy można zastąpić i odwrócić jej stan awarii.
assertRaises
jest krótką metodą, która w zasadzie tworzy instancję unittest.case._AssertRaisesContext
klasy i zwraca ją (patrz jej definicja w unittest.case
module). Możesz zdefiniować własną _AssertNotRaisesContext
klasę, podklasując _AssertRaisesContext
i zastępując jej __exit__
metodę:
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
Zwykle klasy przypadków testowych są definiowane przez dziedziczenie TestCase
. Jeśli zamiast tego dziedziczysz z podklasy 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
wszystkie twoje przypadki testowe będą teraz miały assertNotRaises
dostępną dla nich metodę.