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
unittesty la funciónsumaque vamos a probar. - Clase de Prueba: Definimos
TestMathFunctionsque hereda deunittest.TestCase. - Métodos de Prueba:
test_sumaes un método de prueba. Utilizamos varios métodos deunittest.TestCasepara verificar el comportamiento esperado, comoassertEqual. - 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 queaybsean iguales.assertNotEqual(a, b): Verifica queaybno sean iguales.assertTrue(x): Verifica quexseaTrue.assertFalse(x): Verifica quexseaFalse.assertIs(a, b): Verifica queaybsean el mismo objeto.assertIsNot(a, b): Verifica queaybno sean el mismo objeto.assertIsNone(x): Verifica quexseaNone.assertIsNotNone(x): Verifica quexno seaNone.assertIn(a, b): Verifica queaesté enb.assertNotIn(a, b): Verifica queano esté enb.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()