¿Cómo se escribe una prueba unitaria que falla solo si una función no arroja una excepción esperada?
python
unit-testing
exception
exception-handling
Daryl Spitzer
fuente
fuente
myfunc
debe agregarlos como argumentos a la llamada afirmarRaises. Ver la respuesta de Daryl Spitzer.self.assertRaises(TypeError, mymod.myfunc)
. Puede encontrar una lista completa de las Excepciones incorporadas aquí: docs.python.org/3/library/exceptions.html#bltin-exceptionsself.assertRaises(SomeCoolException, Constructor, arg1)
Desde Python 2.7 puede usar el administrador de contexto para obtener el objeto de excepción real lanzado:
http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises
En Python 3.5 , hay que envolver
context.exception
enstr
, de lo contrario obtendrá unaTypeError
fuente
context.exception
no da el mensaje; Es un tipo.import unittest2
, necesita usarstr()
, es decirself.assertTrue('This is broken' in str(context.exception))
.El código en mi respuesta anterior se puede simplificar a:
Y si una función toma argumentos, simplemente páselos en afirmarRaises como este:
fuente
2.7.15
. Siafunction
inself.assertRaises(ExpectedException, afunction, arg1, arg2)
es el inicializador de clase, debe pasarself
como primer argumento, por ejemplo,self.assertRaises(ExpectedException, Class, self, arg1, arg2)
Respuesta corta:
Use el
self.assertRaises
método como administrador de contexto:Demostración
El enfoque de mejores prácticas es bastante fácil de demostrar en un shell de Python.
La
unittest
bibliotecaEn Python 2.7 o 3:
En Python 2.6, puede instalar un backport de la
unittest
biblioteca de 2.7 , llamado unittest2 , y solo alias comounittest
:Pruebas de ejemplo
Ahora, pegue en su shell de Python la siguiente prueba de seguridad de tipos de Python:
La primera prueba se usa
assertRaises
como administrador de contexto, lo que garantiza que el error se detecte y limpie correctamente, mientras se registra.También podríamos escribirlo sin el administrador de contexto, ver prueba dos. El primer argumento sería el tipo de error que espera generar, el segundo argumento, la función que está probando y los argumentos restantes y los argumentos de palabras clave se pasarán a esa función.
Creo que es mucho más simple, legible y fácil de usar que usar el administrador de contexto.
Ejecutando las pruebas
Para ejecutar las pruebas:
En Python 2.6, probablemente necesitará lo siguiente :
Y su terminal debería generar lo siguiente:
Y vemos que, como esperamos, al intentar agregar ay
1
un'1'
resultado en aTypeError
.Para una salida más detallada, intente esto:
fuente
Su código debe seguir este patrón (esta es una prueba de estilo de módulo de prueba de unidad):
En Python <2.7, esta construcción es útil para verificar valores específicos en la excepción esperada. La función unittest
assertRaises
solo verifica si se produjo una excepción.fuente
assertRaises
, obtendrá un ERROR en lugar de una FALLA.de: http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/
Primero, aquí está la función correspondiente (todavía dum: p) en el archivo dum_function.py:
Aquí está la prueba a realizar (solo se inserta esta prueba):
¡Ahora estamos listos para probar nuestra función! Esto es lo que sucede al intentar ejecutar la prueba:
TypeError se activa y se genera una falla de prueba. El problema es que este es exactamente el comportamiento que queríamos: s.
Para evitar este error, simplemente ejecute la función usando lambda en la llamada de prueba:
El resultado final:
Perfecto !
... y para mi tambien es perfecto !!
Thansk mucho Sr. Julien Lengrand-Lambert
Esta afirmación de prueba en realidad devuelve un falso positivo . Eso sucede porque la lambda dentro de 'afirmarRaises' es la unidad que genera el error de tipo y no la función probada.
fuente
self.assertRaises(TypeError, df.square_value(self.false_int))
llama al método y devuelve el resultado. Lo que quiere es pasar el método y cualquier argumento y dejar que la unidad lo llame:self.assertRaises(TypeError, df.square_value, self.false_int)
Puede crear el suyo propio
contextmanager
para verificar si se produjo la excepción.Y luego puedes usar
raises
así:Si está utilizando
pytest
, esto ya está implementado. Puedes hacerpytest.raises(Exception)
:Ejemplo:
Y el resultado:
fuente
unittest
módulo!Uso doctest [1] en casi todas partes porque me gusta el hecho de documentar y probar mis funciones al mismo tiempo.
Echa un vistazo a este código:
Si coloca este ejemplo en un módulo y lo ejecuta desde la línea de comandos, ambos casos de prueba se evalúan y verifican.
[1] Documentación de Python: 23.2 doctest - Pruebe ejemplos interactivos de Python
fuente
Acabo de descubrir que la biblioteca Mock proporciona un método ClaimRaisesWithMessage () (en su subclase unittest.TestCase), que comprobará no solo que se genera la excepción esperada, sino también que se genera con el mensaje esperado:
fuente
Hay muchas respuestas aquí. El código muestra cómo podemos crear una Excepción, cómo podemos usar esa excepción en nuestros métodos y, por último, cómo puede verificar en una prueba unitaria, las excepciones correctas que se generan.
fuente
Puede usar afirmarRaises desde el módulo unittest
fuente
Si bien todas las respuestas están perfectamente bien, estaba buscando una manera de probar si una función generaba una excepción sin depender de los marcos de prueba de la unidad y tener que escribir clases de prueba.
Terminé escribiendo lo siguiente:
Y falla en la línea correcta:
fuente