Skip to main content

Escribiendo pruebas unitarias con unittest

1. Introducción a unittest

unittest es un módulo estándar de Python para la creación y ejecución de pruebas unitarias. Está inspirado en JUnit, un popular framework de pruebas para Java.

2. Estructura Básica

Una prueba unitaria en unittest se organiza en clases que heredan de unittest.TestCase. Cada método dentro de esta clase que comience con la palabra test se considerará una prueba.

3. Ejemplo Básico

Supongamos que tienes una función en un archivo llamado math_functions.py que deseas probar:

# math_functions.py

def suma(a, b):
return a + b

Ahora, queremos escribir pruebas unitarias para esta función. Creamos un nuevo archivo llamado test_math_functions.py:

# test_math_functions.py

import unittest
from math_functions import suma

class TestMathFunctions(unittest.TestCase):

def test_suma(self):
self.assertEqual(suma(1, 2), 3)
self.assertEqual(suma(-1, 1), 0)
self.assertEqual(suma(-1, -1), -2)

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

4. Detalle de los Componentes

  • Importaciones: Importamos unittest y la función suma que vamos a probar.
  • Clase de Prueba: Definimos TestMathFunctions que hereda de unittest.TestCase.
  • Métodos de Prueba: test_suma es un método de prueba. Utilizamos varios métodos de unittest.TestCase para verificar el comportamiento esperado, como assertEqual.
  • main(): unittest.main() ejecuta todas las pruebas cuando el script se ejecuta directamente.

5. Métodos de Assertion

unittest.TestCase proporciona muchos métodos para verificar los resultados:

  • assertEqual(a, b): Verifica que a y b sean iguales.
  • assertNotEqual(a, b): Verifica que a y b no sean iguales.
  • assertTrue(x): Verifica que x sea True.
  • assertFalse(x): Verifica que x sea False.
  • assertIs(a, b): Verifica que a y b sean el mismo objeto.
  • assertIsNot(a, b): Verifica que a y b no sean el mismo objeto.
  • assertIsNone(x): Verifica que x sea None.
  • assertIsNotNone(x): Verifica que x no sea None.
  • assertIn(a, b): Verifica que a esté en b.
  • assertNotIn(a, b): Verifica que a no esté en b.
  • assertRaises(exception, func, *args, **kwds): Verifica que se lance una excepción específica.

6. Setup y Teardown

A veces, necesitas preparar el entorno antes de ejecutar cada prueba o limpiarlo después. unittest proporciona los métodos setUp() y tearDown() para este propósito:

import unittest
from math_functions import suma

class TestMathFunctions(unittest.TestCase):

def setUp(self):
# Código para preparar el entorno antes de cada prueba
self.a = 1
self.b = 2

def tearDown(self):
# Código para limpiar después de cada prueba
pass

def test_suma(self):
result = suma(self.a, self.b)
self.assertEqual(result, 3)

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

7. Agrupación de Pruebas

Puedes agrupar varias pruebas en un "test suite" y ejecutarlas juntas:

import unittest
from test_math_functions import TestMathFunctions

def suite():
suite = unittest.TestSuite()
suite.addTest(TestMathFunctions('test_suma'))
return suite

if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite())

8. Ejecución de las Pruebas

Para ejecutar las pruebas, puedes usar la línea de comandos:

python -m unittest test_math_functions

O simplemente ejecutar el script si contiene unittest.main():

python test_math_functions.py

9. Pruebas de Casos Especiales y Excepciones

Es importante también probar cómo tu código maneja casos especiales y excepciones. Por ejemplo:

def division(a, b):
if b == 0:
raise ValueError("División por cero")
return a / b

class TestMathFunctions(unittest.TestCase):

def test_division(self):
self.assertEqual(division(4, 2), 2)
self.assertRaises(ValueError, division, 4, 0)

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