Curso
Tutorial de Pruebas Unitarias en Python
Las pruebas unitarias son un método de prueba de software mediante el cual se someten unidades individuales de código fuente a diversas pruebas para determinar si son aptas para su uso. Determina y constata la calidad de tu código.
Por lo general, cuando finaliza el proceso de desarrollo, el desarrollador codifica los criterios, o los resultados que se sabe que son potencialmente prácticos y útiles, en el script de prueba para verificar la corrección de una unidad concreta. Durante la ejecución de los casos de prueba, varios marcos registran las pruebas que fallan algún criterio e informan de ellas en un resumen.
Se espera que los desarrolladores escriban guiones de prueba automatizados, que garanticen que todas y cada una de las secciones o unidades cumplen su diseño y se comportan como se espera de ellas.
Pruebas unitarias en Python
Aunque escribir pruebas manuales para tu código es sin duda una tarea tediosa y que lleva mucho tiempo, el marco de pruebas unitarias incorporado en Python te ha facilitado mucho la vida.
El marco de pruebas unitarias en Python se llama unittest
y viene empaquetado con Python.
Las pruebas unitarias hacen que tu código esté preparado para el futuro, ya que anticipas los casos en los que tu código podría fallar o producir un error. Aunque no puedas prever todos los casos, aborda la mayoría de ellos.
Una unidad puede dividirse en varias categorías:
- Un módulo entero,
- Una función individual,
- Una interfaz completa como una clase o un método.
La mejor forma de escribir pruebas unitarias para tu código es empezar primero con la unidad comprobable más pequeña que pueda tener tu código, luego pasar a otras unidades y ver cómo esa unidad más pequeña interactúa con otras unidades, de esta forma podrías construir una prueba unitaria completa para tus aplicaciones.
El marco de pruebas unitarias de Python se inspiró en JUnit
de Java y tiene características similares a los principales marcos de pruebas unitarias de otros lenguajes. El marco de pruebas unitarias de Python ofrece varias funcionesentre las que se incluyen
- Automatización de pruebas
- Compartir el código de configuración y apagado para las pruebas
- Agregar pruebas en colecciones
- Independencia de las pruebas del marco de información
Ahora vamos a poner un ejemplo y entender por qué necesitas tener pruebas unitarias de tu código.
Primeros pasos con unittest de Python
A continuación, te indicamos los pasos necesarios para utilizar el framework unittest
de Python.
Crear una función cubo
Escribamos un código para calcular el volumen de un cubo en Python
def cuboid_volume(l):
return (l*l*l)
length = [2,1.1, -2.5, 2j, 'two']
for i in range(len(length)):
print ("The volume of cuboid:",cuboid_volume(length[i]))
The volume of cuboid: 8
The volume of cuboid: 1.3310000000000004
The volume of cuboid: -15.625
The volume of cuboid: (-0-8j)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-67e1c37a435f> in <module>
1 for i in range(len(length)):
----> 2 print ("The volume of cuboid:",cuboid_volume(length[i]))
<ipython-input-2-f50464fd88da> in cuboid_volume(l)
1 def cuboid_volume(l):
----> 2 return (l*l*l)
TypeError: can't multiply sequence by non-int of type 'str'
Análisis de resultados
El resultado anterior debería darte alguna intuición sobre la importancia de disponer de una prueba unitaria para tu código. Ahora bien, hay tres cosas que son ciertamente incorrectas en el código anterior:
- En primer lugar, el volumen del cuboide es negativo,
- En segundo lugar, el volumen del cuboide es un número complejo,
- Por último, el código que resulta es un
TypeError
ya que no se puede multiplicar una cadena, que es un no-int.
Afortunadamente, el tercer problema dio error, mientras que el primero y el segundo se resolvieron aunque el volumen del cuboide no puede ser negativo ni un número complejo.
Las pruebas unitarias suelen escribirse como código independiente en un archivo distinto, y puede haber distintas convenciones de nomenclatura que podrías seguir. Puedes escribir el nombre del archivo de pruebas unitarias como name of the code/unit + test
separado por un guión bajo o test + name of the code/unit
separado por un guión bajo.
Por ejemplo, supongamos que el nombre del archivo de código anterior es cuboid_volume.py
, entonces el nombre del código de tu prueba unitaria podría ser cuboid_volume_test.py
Sin más preámbulos, vamos a escribir la prueba unitaria del código anterior.
Utilizar assertAlmostEqual
En primer lugar, vamos a crear un archivo python con el nombre volume_cuboid.py
, que tendrá el código para calcular el volumen y en segundo lugar con el nombre test_volume_cuboid.py
, que tendrá el código de pruebas unitarias.
importa unittest
La clase TestCuboid
hereda el módulo unittest
, y en esta clase definirías varios métodos que querrías que tu prueba unitaria comprobara con tu función cuboid_volume
.
La primera función que definirás es test_volume
, que comprobará si la salida que da tu cuboid_volume
es igual a la que esperas. Para ello, utilizarás el método assertAlmostEqual
.
Prueba 1
class TestCuboid(unittest.TestCase):
def test_volume(self):
self.assertAlmostEqual(cuboid_volume(2),8)
self.assertAlmostEqual(cuboid_volume(1),1)
self.assertAlmostEqual(cuboid_volume(0),0)
self.assertAlmostEqual(cuboid_volume(5.5),166.375)
Vamos a ejecutar el script anterior. Ejecutarías el módulo unittest
como un script especificando -m
mientras lo ejecutas.
!python -m unittest test_volume_cuboid.py
Salida:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
¡Estupendo! Así que has conseguido que funcione tu primer código de prueba unitario.
La prueba se ejecutó correctamente y devolvió, OK
, lo que significa que la función cuboide_volumen funciona como cabría esperar.
Prueba 2
Veamos qué ocurre cuando falla uno de los métodos de assertAlmostEqual
.
Observa que se ha modificado la última afirmación.
!python -m unittest test_volume_cuboid.py
Salida:
F
======================================================================
FAIL: test_volume (test_volume_cuboid.TestCuboid)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\hda3kor\Documents\Unit_Testing_Python\test_volume_cuboid.py", line 15, in test_volume
self.assertAlmostEqual(cuboid_volume(5.5),0)
AssertionError: 166.375 != 0 within 7 places (166.375 difference)
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
Pues bien, a partir de la salida anterior, puedes observar que la última sentencia assert dio como resultado un AssertionError
, por lo tanto un fallo de la prueba unitaria. El módulo de pruebas unitarias de Python te muestra el motivo del fallo, junto con el número de fallos que tiene tu código.
Utilizar assertRaises
Ahora vamos a explorar otro método assert, es decir, assertRaises
, que te ayudará a averiguar si tu función cuboid_volume
maneja correctamente los valores de entrada.
Supongamos que quieres comprobar si tu función cuboid_volume
maneja la clase o tipo de entrada, por ejemplo, si pasas una cadena como entrada, la manejará como una excepción o con una condición if, ya que la longitud del cuboide nunca puede ser una cadena.
!python -m unittest test_volume_cuboid.py
Salida:
F.
======================================================================
FAIL: test_input_value (test_volume_cuboid.TestCuboid)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\hda3kor\Documents\Unit_Testing_Python\test_volume_cuboid.py", line 17, in test_input_value
self.assertRaises(TypeError, cuboid_volume, True)
AssertionError: TypeError not raised by cuboid_volume
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
¡Estupendo! Por lo tanto, a partir de la salida anterior, es evidente que tu código volume_cuboid.py
no se ocupa correctamente de la entrada que se le pasa.
Modificar la función cubo
Vamos a añadir una condición en el volume_cuboid.py
para comprobar si la entrada o la longitud del cuboide es un booleano o una cadena y lanzar un error.
!python -m unittest test_volume_cuboid.py
Salida:
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
Ejecutar el script de pruebas de Python en el laboratorio Jupyter
Ahora vamos a ejecutar el script de prueba dentro del laboratorio jupyter. Para conseguirlo, primero definirías el script de prueba en el laboratorio jupyter, como se muestra a continuación.
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 25 20:16:58 2020
@author: Aditya
"""
from volume_cuboid import *
import unittest
class TestCuboid(unittest.TestCase):
def test_volume(self):
self.assertAlmostEqual(cuboid_volume(2),8)
self.assertAlmostEqual(cuboid_volume(1),1)
self.assertAlmostEqual(cuboid_volume(0),1)
def test_input_value(self):
self.assertRaises(TypeError, cuboid_volume, True)
A continuación, utilizarás el método unittest.main()
para ejecutar el script de prueba, puedes pasar varios argumentos al método siguiente, de los cuales uno es verbosity level
.
Experimentemos con distintos niveles de verbosidad y veamos cómo cambia la descripción de salida.
Verbosidad 0
unittest.main(argv=[''],verbosity=0, exit=False)
Output:
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
<unittest.main.TestProgram at 0x1de02774348>
Verbosidad 1
unittest.main(argv=[''],verbosity=1, exit=False)
Output:
..
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
<unittest.main.TestProgram at 0x1de027a1cc8>
Verbosidad 2
unittest.main(argv=[''],verbosity=2, exit=False)
Output:
test_input_value (__main__.TestCuboid) ... ok
test_volume (__main__.TestCuboid) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
<unittest.main.TestProgram at 0x1de027a8308>
Visualizar el error de aserción
Por último, modifiquemos el assertAlmostEqual
final en el método test_volume
y analicemos cómo el nivel de verbosidad 2 mostrará el fallo del método.
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 25 20:16:58 2020
@author: Aditya
"""
from volume_cuboid import *
import unittest
class TestCuboid(unittest.TestCase):
def test_volume(self):
self.assertAlmostEqual(cuboid_volume(2),8)
self.assertAlmostEqual(cuboid_volume(1),1)
self.assertAlmostEqual(cuboid_volume(0),1)
def test_input_value(self):
self.assertRaises(TypeError, cuboid_volume, True)
unittest.main(argv=[''],verbosity=2, exit=False)
Salida:
test_input_value (__main__.TestCuboid) ... ok
test_volume (__main__.TestCuboid) ... FAIL
======================================================================
FAIL: test_volume (__main__.TestCuboid)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<ipython-input-28-46ad33b909ee>", line 14, in test_volume
self.assertAlmostEqual(cuboid_volume(0),1)
AssertionError: 0 != 1 within 7 places (1 difference)
----------------------------------------------------------------------
Ran 2 tests in 0.003s
FAILED (failures=1)
<unittest.main.TestProgram at 0x1de027b5448>
Resumen
De los resultados anteriores pueden extraerse las siguientes conclusiones:
- El nivel de verbosidad 0 sólo muestra cuántas pruebas se ejecutaron, es decir, 2 pruebas junto con el tiempo que se tardó en ejecutarlas,
- Verbosidad nivel 1 añade dos puntos .. que significa que se han ejecutado dos pruebas,
- El nivel de verbosidad 2 muestra los nombres detallados de los métodos que se ejecutaron junto con su estado
OK
oFAIL
.
Métodos disponibles de unittest Assert
Hay muchos métodos de afirmación en el módulo de pruebas unitarias de Python, que podrías aprovechar para tus pruebas.
Métodos de afirmación utilizados habitualmente
Fuente: documentación de unittest
Controles de producción
Utilizando los siguientes métodos, puedes comprobar la producción de excepciones, advertencias y mensajes de registro.
Fuente: documentación de unittest
Métodos para tareas específicas
Fuente: documentación de unittest
Para conocer en detalle los métodos de assert
, consulta la documentación oficial de Python de Python.
También puedes conocerlos con ayuda del módulo Pydoc
, que es similar a una función help
en Python. A continuación se muestra una demostración de cómo podrías utilizar el módulo Pydoc para leer la documentación del método assertCountEqual
.
!python -m pydoc unittest.TestCase.assertCountEqual
Salida:
Help on function assertCountEqual in unittest.TestCase:
unittest.TestCase.assertCountEqual = assertCountEqual(self, first, second, msg=None)
An unordered sequence comparison asserting that the same elements,
regardless of order. If the same element occurs more than once,
it verifies that the elements occur the same number of times.
self.assertEqual(Counter(list(first)),
Counter(list(second)))
Example:
- [0, 1, 1] and [1, 0, 1] compare equal.
- [0, 0, 1] and [0, 1] compare unequal.
Conclusión
Este tutorial fue una introducción básica a las pruebas unitarias en python y su importancia como desarrollador. Un buen ejercicio para ti sería escribir un módulo de pruebas unitarias para cualquiera de tus proyectos anteriores. Esto te dará una buena experiencia práctica en la escritura de pruebas unitarias. Además, prueba a explorar el resto de métodos Assert. Puedes leer más sobre las pruebas unitarias con nuestro tutorial de Pytest.
Si te estás iniciando en Python y quieres aprender más, sigue nuestro curso de Introducción a la Ciencia de Datos en Python en Python.
Conviértete en Desarrollador Python

Soy un científico de datos certificado que disfruta creando aplicaciones de aprendizaje automático y escribiendo blogs sobre ciencia de datos. Actualmente me centro en la creación de contenidos, la edición y el trabajo con grandes modelos lingüísticos.
¡Aprende más sobre Python con estos cursos!
Curso
Intermediate Python for Developers
Curso
Python Toolbox

Tutorial
Cómo utilizar Pytest para pruebas unitarias
Tutorial
Tutorial de Python sobre conjuntos y teoría de conjuntos

DataCamp Team
13 min
Tutorial
Tutorial de funciones de Python
Tutorial
Tutorial Python Docstrings : Ejemplos y Formato de Cadenas Doc Pydoc, Numpy, Sphinx
Tutorial