È possibile definire assertNotRaises
riutilizzando circa il 90% dell'implementazione originale di assertRaises
nel unittest
modulo. Con questo approccio, si finisce con un assertNotRaises
metodo che, a parte la sua condizione di fallimento inversa, si comporta in modo identicoassertRaises
.
TLDR e demo live
Risulta sorprendentemente facile aggiungere un assertNotRaises
metodo a unittest.TestCase
(mi ci è voluto circa 4 volte più tempo per scrivere questa risposta come ha fatto il codice). Ecco una demo live del assertNotRaises
metodo in azione . Proprio comeassertRaises
, puoi passare un callable e discutere assertNotRaises
, oppure puoi usarlo in una with
dichiarazione. La demo live include casi di test che lo dimostranoassertNotRaises
funziona come previsto.
Dettagli
L'implementazione di assertRaises
aunittest
è abbastanza complicata, ma con un po 'di sottoclasse intelligente puoi sovrascrivere e invertire la sua condizione di fallimento.
assertRaises
è un metodo breve che fondamentalmente crea solo un'istanza della unittest.case._AssertRaisesContext
classe e la restituisce (vedere la sua definizione nel unittest.case
modulo). Puoi definire la tua _AssertNotRaisesContext
classe effettuando la sottoclasse _AssertRaisesContext
e sovrascrivendo il suo __exit__
metodo:
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
Normalmente si definiscono le classi di test case facendole ereditare da TestCase
. Se invece erediti da una sottoclasse 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
tutti i casi di test avranno ora il assertNotRaises
metodo a loro disposizione.