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 variasfuncionesentre 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 frameworkunittest de Python.
Crear una función cubo
Escribamos un código para calcular el volumen de un cubo en Python
defcuboid_volume(l):return(l*l*l)
length =[2,1.1,-2.5,2j,'two']for i inrange(len(length)):print("The volume of cuboid:",cuboid_volume(length[i]))Con la tecnología de
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'Con la tecnología de
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 sercuboid_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.
importaunittest
La claseTestCuboid hereda el módulounittest, 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étodoassertAlmostEqual.
Prueba 1
classTestCuboid(unittest.TestCase):deftest_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)Con la tecnología de
Vamos a ejecutar el script anterior. Ejecutarías el módulo unittest como un script especificando -m mientras lo ejecutas.
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)Con la tecnología de
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.
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)Con la tecnología de
¡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.
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OKCon la tecnología de
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
classTestCuboid(unittest.TestCase):deftest_volume(self):
self.assertAlmostEqual(cuboid_volume(2),8)
self.assertAlmostEqual(cuboid_volume(1),1)
self.assertAlmostEqual(cuboid_volume(0),1)deftest_input_value(self):
self.assertRaises(TypeError, cuboid_volume,True)Con la tecnología de
A continuación, utilizarás el métodounittest.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.TestProgramat0x1de02774348>Con la tecnología de
Verbosidad 1
unittest.main(argv=[''],verbosity=1, exit=False)
Output:
..
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
<unittest.main.TestProgramat0x1de027a1cc8>Con la tecnología de
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.TestProgramat0x1de027a8308>Con la tecnología de
Visualizar el error de aserción
Por último, modifiquemos el assertAlmostEqual final en el métodotest_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
classTestCuboid(unittest.TestCase):deftest_volume(self):
self.assertAlmostEqual(cuboid_volume(2),8)
self.assertAlmostEqual(cuboid_volume(1),1)
self.assertAlmostEqual(cuboid_volume(0),1)deftest_input_value(self):
self.assertRaises(TypeError, cuboid_volume,True)
unittest.main(argv=[''],verbosity=2, exit=False)Con la tecnología de
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.TestProgramat0x1de027b5448>Con la tecnología de
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 o FAIL.
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.
Para conocer en detalle los métodos deassert, consulta la documentación oficial de Pythonde 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étodoassertCountEqual.
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.Con la tecnología de
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 nuestrotutorial de Pytest.
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 sobre los conjuntos en Python: qué son, cómo crearlos, cuándo usarlos, funciones incorporadas y su relación con las operaciones de la teoría de conjuntos.
Descubre cómo escribir funciones en Python reutilizables y eficientes. Domina los parámetros, las sentencias return y temas avanzados como las funciones lambda. Organiza mejor tu código con main() y otras buenas prácticas.
Aprende a crear e importar módulos de Python. ¡Descubre las mejores prácticas, ejemplos y consejos para escribir código Python reutilizable, organizado y eficiente!
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
unittesty 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:
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
JUnitde 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 incluyenAhora 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
unittestde Python.Crear una función cubo
Escribamos un código para calcular el volumen de un cubo en Python
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:
TypeErrorya 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 + testseparado por un guión bajo otest + name of the code/unitseparado 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 sercuboid_volume_test.pySin 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 nombretest_volume_cuboid.py, que tendrá el código de pruebas unitarias.importa unittest
La clase
TestCuboidhereda el módulounittest, y en esta clase definirías varios métodos que querrías que tu prueba unitaria comprobara con tu funcióncuboid_volume.La primera función que definirás es
test_volume, que comprobará si la salida que da tucuboid_volumees igual a la que esperas. Para ello, utilizarás el métodoassertAlmostEqual.Prueba 1
Vamos a ejecutar el script anterior. Ejecutarías el módulo
unittestcomo un script especificando-mmientras lo ejecutas.Salida:
¡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.
Salida:
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óncuboid_volumemaneja correctamente los valores de entrada.Supongamos que quieres comprobar si tu función
cuboid_volumemaneja 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.Salida:
¡Estupendo! Por lo tanto, a partir de la salida anterior, es evidente que tu código
volume_cuboid.pyno 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.pypara comprobar si la entrada o la longitud del cuboide es un booleano o una cadena y lanzar un error.Salida:
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.
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 esverbosity level.Experimentemos con distintos niveles de verbosidad y veamos cómo cambia la descripción de salida.
Verbosidad 0
Verbosidad 1
Verbosidad 2
Visualizar el error de aserción
Por último, modifiquemos el
assertAlmostEqualfinal en el métodotest_volumey analicemos cómo el nivel de verbosidad 2 mostrará el fallo del método.Salida:
Resumen
De los resultados anteriores pueden extraerse las siguientes conclusiones:
OKoFAIL.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ónhelpen 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étodoassertCountEqual.Salida:
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.