unittest unit tests run examples example espaƱol assertraises assertequal python unit-testing

tests - Python unittest-opuesto a assertRaises?



unittest python 3 (7)

Hola: quiero escribir una prueba para establecer que una excepción no se produce en una circunstancia determinada.

Esa es la suposición predeterminada: las excepciones no se generan.

Si no dices nada más, eso se asume en todas las pruebas.

No tienes que escribir una afirmación para eso.

Quiero escribir una prueba para establecer que una excepción no se produce en una circunstancia determinada.

Es sencillo probar si se genera una excepción ...

sInvalidPath=AlwaysSuppliesAnInvalidPath() self.assertRaises(PathIsNotAValidOne, MyObject, sInvalidPath)

... pero como puedes hacer lo contrario

Algo como esto i lo que busco ...

sValidPath=AlwaysSuppliesAValidPath() self.assertNotRaises(PathIsNotAValidOne, MyObject, sValidPath)


Me ha resultado útil realizar la prueba de unittest parche de mono de la siguiente manera:

def assertMayRaise(self, exception, expr): if exception is None: try: expr() except: info = sys.exc_info() self.fail(''%s raised'' % repr(info[0])) else: self.assertRaises(exception, expr) unittest.TestCase.assertMayRaise = assertMayRaise

Esto aclara la intención al probar la ausencia de una excepción:

self.assertMayRaise(None, does_not_raise)

Esto también simplifica las pruebas en un bucle, que a menudo me encuentro haciendo:

# ValueError is raised only for op(x,x), op(y,y) and op(z,z). for i,(a,b) in enumerate(itertools.product([x,y,z], [x,y,z])): self.assertMayRaise(None if i%4 else ValueError, lambda: op(a, b))


Puede definir assertNotRaises reutilizando aproximadamente el 90% de la implementación original de assertRaises en el módulo unittest . Con este enfoque, usted termina con un método assertNotRaises que, aparte de su condición de falla inversa, se comporta de manera idéntica a assertRaises .

TLDR y demostración en vivo

Resulta sorprendentemente fácil agregar un método assertNotRaises a unittest.TestCase (me tomó aproximadamente 4 veces más tiempo escribir esta respuesta como lo hizo con el código). Aquí hay una demostración en vivo del método assertNotRaises en acción . Al igual que assertRaises , puede pasar un llamable y args a assertNotRaises , o puede usarlo en una declaración with . La demostración en vivo incluye un caso de prueba que demuestra que assertNotRaises funciona según lo previsto.

Detalles

La implementación de assertRaises en unittest es bastante complicada, pero con un poco de subclasificación inteligente puede anular e invertir su condición de falla.

assertRaises es un método corto que básicamente crea una instancia de la clase unittest.case._AssertRaisesContext y la devuelve (consulte su definición en el módulo unittest.case ). Puede definir su propia clase _AssertRaisesContext subclasificando _AssertRaisesContext y anulando su método __exit__ :

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 usted define las clases de casos de prueba haciéndolos heredar de TestCase . Si en cambio hereda de una subclase 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

todos sus casos de prueba ahora tendrán el método assertNotRaises disponible para ellos.


Si pasa una clase de excepción a assertRaises() , se proporciona un administrador de contexto. Esto puede mejorar la legibilidad de sus pruebas:

# raise exception if Application created with bad data with self.assertRaises(pySourceAidExceptions.PathIsNotAValidOne): application = Application("abcdef", "")

Esto le permite probar casos de error en su código.

En este caso, está probando que PathIsNotAValidOne se PathIsNotAValidOne cuando pasa parámetros no válidos al constructor de la aplicación.


Simplemente llame a la función. Si genera una excepción, el marco de prueba de la unidad lo marcará como un error. Es posible que desee agregar un comentario, por ejemplo:

sValidPath=AlwaysSuppliesAValidPath() # Check PathIsNotAValidOne not thrown MyObject(sValidPath)


Soy el póster original y acepté la respuesta anterior de DGH sin haberla utilizado primero en el código.

Una vez que lo usé, me di cuenta de que necesitaba un pequeño ajuste para hacer lo que yo necesitaba que hiciera (para ser justos con DGH, él / ella sí dijo "o algo similar"!).

Pensé que valía la pena publicar el tweak aquí para el beneficio de otros:

try: a = Application("abcdef", "") except pySourceAidExceptions.PathIsNotAValidOne: pass except: self.assertTrue(False)

Lo que intentaba hacer aquí era garantizar que si se intentaba crear una instancia de un objeto de Aplicación con un segundo argumento de espacios, se generaría el pySourceAidExceptions.PathIsNotAValidOne.

Creo que usar el código anterior (basado en gran medida en la respuesta de DGH) hará eso.


def run_test(self): try: myFunc() except ExceptionType: self.fail("myFunc() raised ExceptionType unexpectedly!")