¿Cómo testear tu código Python?



@eduardo_gpg

Número de visitas 2376

Tiempo de lectura 5 min

19 Enero 2022

En una entrega anterior hablamos sobre el docstring de Python, de como este nos permite tanto documentar como testear nuestro código. Es un posts sumamente interesante, así que si aun no lo haz visto, te invito a que lo hagas, no te arrepentirás. 😎

Pues bien, siguiente con el tema de testing, para esta nueva entrega me gustaría abordar el tema de como testar nuestro código Python utilizando la librería pytest. Una de las librerías más populares que podemos encontrar en el mercado para este fin.

Es un post sumamente interesante, al cual no dudo podrás sacarle el máximo provecho posible. Así que, sin más introducción, pongamos manos a la obra.

Assert 🐛

De lo primero que debemos hablar es sin duda de assert. Verás, la palabra reservada assert nos permite evaluar una condición, Si la condición es verdadera el programa continua con su ejecución, sin embargo, si la condición es falsa entonces una excepción será lanzada. 😲

Su estructura es la siguiente.

assert <condición>, <Mensaje opcional de error>

Veamos un par de ejemplos.

assert 10 < 100, 'La expresión da como resultado True'
assert True, 'La expresión da como resultado True'

En caso la condición no se cumpla, entonces una excepción de tipo AssertionError será lanzada. 🤯

>>> assert 10 > 20, 'Lo sentimos, 10 no es mayor a 20.'

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: Lo sentimos, 10 no es mayor a 20.

Por supuesto, una vez conozcamos el error ya podremos implementar el bloque try and except:

try:
    assert 10 > 20, 'Lo sentimos, 10 no es mayor a 20.'
except AssertionError as err:
    print('Lo sentimos, tu prueba no ha sido valida')

Lo sentimos, tu prueba no ha sido valida

Si bien es cierto, pudiésemos obtener el mismo resultado utilizando la palabra reservada raise.

if condicion:
    raise AssertionError()

El uso assert resulta ser mucho más practico, ya que en una sola línea condicionamos y lanzamos la excepción, 🧐 lo cual sin duda nos viene de maravilla siembre que deseemos comprobar el funcionamiento de nuestros programas y detectar posibles errores.

Listo, una vez a sabiendas que podemos testear nuestro código Python con las herramientas que el lenguaje mismo nos ofrece, ahora sí, hablemos de pytets.

Pytest 🤖

Para poder trabajar con la librería pytest debemos tener en cuenta que esta no se encuentra dentro de la biblioteca estándar de Python, por lo tanto, será necesario instarla. Yo te recomiendo lo hagamos mediante un entorno de desarrollo.

Si aun no conoces acerca de los entornos virtuales en Python, te comparto un post en donde te lo explicamos más en detalle.

Creamos el entorno.

python -m venv env

Activamos el entorno.

source env/bin/activate

Instalación de pytets.

pip install pytest

Una vez pytest haya sido instalado ya podremos hacer uso de él.

Para este post ¿Qué te parece si resolvemos el siguiente ejercicio? Enteros + 10.

Mi solución es la siguiente.

main.py

def consecutivos(integers):
    last = integers[0]

    for pos in range(1, len(integers)):
        if last + 10 == integers[pos]:
            last = integers[pos]
        else:
            return False

    return True

Para probar que mi función cumpla con los requerimientos implementaremos un para de casos de pruebas.

Para las pruebas lo recomendables es crear un nuevo archivo con extensión .py. Este archivo tendrá el prefijo test. Y dentro del archivo, mediante funciones, debemos definir todos los casos de pruebas con los cuales queremos probar.

Todas las funciones, de forma obligatoria, deberán comenzar con el prefijo test.

test_consecutivos.py

from main import consecutivos

def test_available_list():
    listado = [10, 20, 30, 40, 50, 60]
    response = consecutivos(listado)

    assert response == True


def test_unavailable_list():
    listado = [10, 20, 31, 41, 51, 61]
    response = consecutivos(listado)

    assert response == False

Cada función es independiente, por lo que recae en cada una de ellas proporcionar los datos necesarios para poder realizar su correspondiente prueba.

Para probar esto ejecutamos el siguiente comando en consola.

pytest​​ ​​test_consecutivos.py

Si todas las pruebas se han ejecutado correctamente deberíamos visualizar algo como lo siguiente.

========== test session starts ==========
platform linux -- Python 3.9.7, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/eduardo/projects/cf_translate
plugins: anyio-3.5.0
collected 2 items

test_consecutivos.py ..

Podrá observar, mediante puntos de color verde, la cantidad de pruebas ejecutadas y cuantas de ellas han sido satisfactorias.

Por otro lado, si una de las pruebas llegará a fallar, esta será remarcada en color rojo.

========== test session starts ==========
platform linux -- Python 3.9.7, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/eduardo/projects/cf_translate
plugins: anyio-3.5.0
collected 2 items

test_consecutivos.py .F                                                                                                                         [100%]

========== FAILURES ==========
________________________________________________________________ test_unavailable_list ________________________________________________________________

    def test_unavailable_list():
        listado = [10, 20, 31, 41, 51, 61]
        response = consecutivos(listado)

>       assert response == True
E       assert False == True

test_consecutivos.py:14: AssertionError
========== short test summary info ==========
FAILED test_consecutivos.py::test_unavailable_list - assert False == True
==========1 failed, 1 passed in 0.02s ==========

Si queremos conocer más información acerca de las pruebas podemos utilizar la bandera -v (verbose).

pytest -v test_consecutivos.py

Probar un solo caso

Si quisiéramos probar una sola función el comando sería el siguiente.

pytest -v <Archivo Python>.py::<Función a probar>

En mi caso.

pytest -v test_consecutivos.py::test_unavailable_list

Saltar pruebas

Algo interesante de pytest es sin duda sus decoradores, con los cuales podremos dotar de más información a las pruebas definidas. 🍻

Uno de estos decoradores más importantes es skip, que, tal y como su nombre lo dice, nos permite saltar las pruebas.

Veamos un ejemplo.

import pytest
from main import consecutivos

@pytest.mark.skip(reason='No comprendo del todo lo que se debe hacer.')
def test_unavailable_list():
    listado = [10, 20, 31, 41, 51, 61]
    response = consecutivos(listado)

    assert response == False

Si ejecutamos visualizaremos en consola las pruebas omitidas.

(env) eduardo@DESKTOP-T7CIBSF:~/projects/cf_translate$ pytest -v test_consecutivos.py
==========  test session starts ========== 
platform linux -- Python 3.9.7, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /home/eduardo/projects/cf_translate/env/bin/python3.9
cachedir: .pytest_cache
rootdir: /home/eduardo/projects/cf_translate
plugins: anyio-3.5.0
collected 1 item

test_consecutivos.py::test_unavailable_list SKIPPED (No comprendo del todo lo que se debe hacer.)

De igual forma podemos omitir pruebas bajo ciertas condiciones, para ello hacemos uso del decorador skipif.

import pytest
from main import consecutivos

def condition():
    return False


@pytest.mark.skipif(condition=condition, reason="La función no permite la ejecución de la prueba.")
def test_unavailable_list():
    listado = [10, 20, 31, 41, 51, 61]
    response = consecutivos(listado)

    assert response == False

Para este ejemplo he defino una función (conditon) quien es la encargada de validar si la prueba puede o no ejecutarse. Dentro de la función podemos definir la lógica que deseemos; por ejemplo si se logro o no una autenticación con un servidor, si la base de datos no se encuentra construida, si ficheros del sistema existen o no etc... Mediante esta función sabremos si existen las condiciones para poder testear nuestro código.

Bastante cool ¿no lo crees? 🤠

Conclusión

Como pudimos observar la librería pytets es sin duda muy interesante. No por el hecho que con ella podemos testear nuestro código, si no que además podemos definir reglas para ello. 🧐

La verdad pytest es sin duda una de mis librerías favoritas. Así que si quieres una segunda parte, con más decoradores y tips de, no olvides dejárnoslo saber en la sección de comentarios.

Bien, sin más por escribir, muchas gracias por llegar al final. 🍹


¿El contenido te resulto de ayuda?

Para poder dejar tu opinión es necesario ser un usuario autenticado. Login

Más Tips y Ejercicios 🐍

Adquiere una subscripción PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 🔓
Nuevo límite: Incrementa tu límite de ejercicios por semana. 🚀
Contenido único: Recibe semanalmente recursos exclusivos de Python (Videos, Artículos y Capitulos del libro PyWombat, comienza como desarrollador Python. 🐍