Python assert Excepción

Neema Muganga 10 octubre 2023
  1. Uso de Context Manager para detectar la excepción de afirmación de Python
  2. Uso de argumentos de palabras clave para detectar la excepción de afirmación de Python
Python assert Excepción

Este artículo lleva a uno a comprender el concepto assert como una unidad de prueba, para probar que las funciones pueden generar excepciones (errores detectados durante la ejecución del código) sin necesariamente salir de la ejecución. En otras palabras, la excepción lanzada está encapsulada.

Esta prueba pasará si se genera una excepción. Se produce un error si se lanza una excepción diferente a la esperada. En una instancia en la que no se genera ninguna excepción, la prueba falla.

Uso de Context Manager para detectar la excepción de afirmación de Python

De manera similar a cómo permite la asignación y liberación de recursos cuando es necesario en el concepto general de Python, el contexto aquí se apodera del objeto de excepción real que se lanza durante la prueba.

Almacena este atributo de excepción en el objeto si es necesario realizar una verificación de rendimiento adicional en la excepción generada.

Para probar que una función falla o pasa si se lanza una excepción o no, emplearemos TestCase.assertRaises del módulo unittest.

Veamos un ejemplo práctico usando el administrador de contexto.

import unittest


class TestCase(unittest.TestCase):
    def test_nameerror(self):
        with self.assertRaises(Exception):
            100 * (someNumber / 5)


if __name__ == "__main__":
    unittest.main()

Producción :

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

En el código de ejemplo, la prueba pasa porque esperamos que se lance una excepción. Estamos dividiendo 5 por una variable indefinida someNumber. Por lo tanto, la función lanza una excepción NameError. Por lo tanto, nuestra prueba pasa como se muestra en . en la primera línea de la salida.

Veamos un ejemplo en el que la prueba falla cuando no se lanza una excepción.

import unittest


class TestCase(unittest.TestCase):
    def test_nameerror(self):
        with self.assertRaises(Exception):
            someNumber = 10
            100 * (someNumber / 5)


if __name__ == "__main__":
    unittest.main()

Producción :

F
======================================================================
FAIL: test_nameerror (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):  File "c:\Users\Neema\Desktop\Article Requirement Spec and Example 
Articles\Article Requirement Spec 
and Example Articles\fah.py", line 106, in test_nameerror
    100 * (someNumber/5)
AssertionError: Exception not raised

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)

En este código de ejemplo, definimos un valor para someNumber y luego realizamos la expresión aritmética con él.

El resultado nos muestra que la prueba falla como se esperaba. No esperamos que se lance ninguna excepción de NameError esta vez, ya que existe un valor definido para someNumber.

También podemos implementar el administrador de contexto usando excepciones definidas por el usuario como en el siguiente ejemplo.

import unittest


def user_function():
    raise Exception("A user-defined exception")


class MyTestCase(unittest.TestCase):
    def test_userexception(self):
        with self.assertRaises(Exception) as context:
            user_function()

        self.assertTrue("A user-defined exception" in str(context.exception))


if __name__ == "__main__":
    unittest.main()

Producción :

.
----------------------------------------------------------------------
Ran 1 test in 0.006s

OK

Recuerde usar str para encerrar la context.exception para evitar obtener un TypeError.

Introducimos assertTrue, una biblioteca de unittest que compara un valor de prueba con verdadero en las pruebas unitarias.

También puede optar por utilizar assertIn en lugar de assertTrue.

Ejemplo:

import unittest


def user_function():
    raise Exception("A use defined exception")


class MyTestCase(unittest.TestCase):
    def test_userexception(self):
        with self.assertRaises(Exception) as context:
            user_function()

        self.assertIn("A use defined exception", str(context.exception))


if __name__ == "__main__":
    unittest.main()

Vemos la misma salida donde se producirán los pases de prueba.

Uso de argumentos de palabras clave para detectar la excepción de afirmación de Python

A diferencia del administrador de contexto, donde solo pasamos la excepción a assertRaises(), también pasamos la llamada a la función y los parámetros de la función como argumentos de palabras clave para evocar la excepción.

Sintaxis

assertRaises(exception, function, *args, **keywords)

Ejemplo:

import unittest


class MyTestCase(unittest.TestCase):
    def test_division_by_error(self):
        import operator

        self.assertRaises(ZeroDivisionError, operator.floordiv, 55, 0)


if __name__ == "__main__":
    unittest.main()

Producción :

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

El código de ejemplo anterior usó assertRaises() con argumentos de palabras clave. Le pasamos la excepción ZeroDivisionError esperada después de intentar dividir un número con cero. Importamos la función de operador usada con la función de operador floordiv como segundo argumento. Los valores de los parámetros aquí son los terceros parámetros; 55 para dividir por 0.

La última aplicación de assert es cuando pasamos una excepción diferente a la esperada a assertRaises(). En cambio, se produce un error.

Usando el mismo código de ejemplo que acabamos de usar anteriormente, implementemos esto.

import unittest


class MyTestCase(unittest.TestCase):
    def test_division_by_error(self):
        import operator

        self.assertRaises(TypeError, operator.floordiv, 55, 0)


if __name__ == "__main__":
    unittest.main()

Producción :

E
======================================================================
ERROR: test_division_by_error (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):  File "c:\Users\Neema\Desktop\Article Requirement Spec and Example 
Articles\user.py", line 16, in test_division_by_error
    self.assertRaises(TypeError, operator.floordiv, 55, 0)
  File "C:\Users\Neema\AppData\Local\Programs\Python\Python39\lib\unittest\case.py", line 733, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "C:\Users\Neema\AppData\Local\Programs\Python\Python39\lib\unittest\case.py", line 201, in handle
    callable_obj(*args, **kwargs) 
ZeroDivisionError: integer division or modulo by zero

----------------------------------------------------------------------
Ran 1 test in 0.031s

FAILED (errors=1)

A partir de la salida, se produce un rastreo de error. Esperamos una excepción ZeroDivisionError cuando dividimos un número por cero. En su lugar, pasamos una excepción TypeError aplicada al realizar una operación aritmética entre diferentes tipos de datos, digamos una cadena y un entero.

Artículo relacionado - Python Exception