Tutorial PyTest: Instala, Escribe y Ejecuta Tests en Python con Confianza
¿Qué es PyTest?
PyTest es un potente framework de testing open-source que permite a desarrolladores escribir casos de test concisos y escalables para proyectos Python —ya sean unit tests, integration tests o checks end-to-end de APIs. Soporta ejecución paralela, inyección de fixtures, parametrización y reportes ricos out-of-the-box.
Por Qué Elegir PyTest
- Sintaxis simple y legible que reduce boilerplate
- Descubrimiento y ejecución automática de tests
- Ejecuta tests específicos o grupos con
-ky markers - Soporte integrado para ejecuciones paralelas vía
pytest-xdist - Extensible mediante fixtures, hooks y plugins
- Gratuito y activamente mantenido por la comunidad
Instalando PyTest
Instala la última versión estable con pip:
pip install pytest
Verifica la instalación:
pytest --version
Para control de versión específico, puedes fijar a una release, ej. pip install pytest==7.4.0.
Primeros Pasos: Un Test Básico
Crea un directorio de proyecto y añade un archivo de test llamado test_sample1.py:
import pytest
def test_file1_method1():
x = 5
y = 6
assert x + 1 == y, "Falló la suma"
assert x == y, "Los valores deberían coincidir"
def test_file1_method2():
x = 5
y = 6
assert x + 1 == y, "Falló la suma"
Ejecuta la suite de tests:
pytest
Ejemplo de salida:
==================== test session starts ====================
collected 2 items
test_sample1.py F. [100%]
=================================== FAILURES ===================================
...
Entendiendo Assertions
Las assertions de PyTest se comportan como statements estándar assert de Python. En fallo, el test detiene ejecución y PyTest reporta ubicación exacta y mensaje:
assert "hola" == "Hai", "Saludo no coincide"
Reglas de Descubrimiento de Tests
- Los archivos deben comenzar con
test_o terminar en_test.py. - Las funciones de test deben comenzar con
test_. - Otros archivos o funciones se ignoran salvo especificación explícita.
Ejecutando Tests Específicos
Ejecuta todos los tests en un directorio:
pytest
Ejecuta un solo archivo:
pytest test_sample1.py
Filtra por substring:
pytest -k method1 -v
Ejecuta por marker:
pytest -m set1
Ejecución Paralela
Instala plugin xdist y lanza ejecución paralela con 4 workers:
pip install pytest-xdist pytest -n 4
Usando Fixtures
Define lógica de setup reutilizable una vez e inyéctala en tests:
import pytest
@pytest.fixture
def supply_data():
return [25, 35, 45]
def test_compare_with_first(supply_data):
assert supply_data[0] == 25
Coloca código de fixture en conftest.py para compartir entre múltiples módulos de test.
Tests Parametrizados
Ejecuta un solo test con muchas entradas:
import pytest
@pytest.mark.parametrize("a, b, expected", [(5, 5, 10), (3, 5, 8)])
def test_add(a, b, expected):
assert a + b == expected
Saltando y Fallos Esperados
Usa markers para saltar o esperar fallos sin contaminar resultados:
import pytest
@pytest.mark.skip(reason="Feature no disponible aún")
def test_future_feature():
pass
@pytest.mark.xfail(reason="Bug conocido")
def test_known_issue():
assert 1 == 2
Generando Reportes XML
Genera archivo XML compatible JUnit para pipelines CI:
pytest -v --junitxml=result.xml
Ejemplo Práctico: Testeando una API Pública
Abajo, framework mínimo que ejercita https://reqres.in/:
# conftest.py
import pytest
@pytest.fixture
def base_url():
return "https://reqres.in/api"
# test_list_user.py
import requests, json
import pytest
@pytest.mark.parametrize("user_id, first_name", [(1, "George"), (2, "Janet")])
def test_valid_user(base_url, user_id, first_name):
resp = requests.get(f"{base_url}/users/{user_id}")
data = json.loads(resp.text)
assert resp.status_code == 200
assert data["data"]["id"] == user_id
assert data["data"]["first_name"] == first_name
def test_invalid_user(base_url):
resp = requests.get(f"{base_url}/users/50")
assert resp.status_code == 404
# test_login_user.py
import requests, json
import pytest
def test_login_success(base_url):
payload = {"email": "test@test.com", "password": "something"}
resp = requests.post(f"{base_url}/login/", data=payload)
data = json.loads(resp.text)
assert resp.status_code == 200
assert data["token"] == "QpwL5tke4Pnpja7X"
def test_login_missing_password(base_url):
payload = {"email": "test@test.com"}
resp = requests.post(f"{base_url}/login/", data=payload)
data = json.loads(resp.text)
assert resp.status_code == 400
assert data["error"] == "Missing password"
Conclusión
Este tutorial cubrió instalación de PyTest, escritura de tests claros, uso de fixtures y markers, ejecución paralela, generación de reportes XML y construcción de una suite simple de tests de API. Con estas bases, puedes escalar tus prácticas de testing en Python con confianza.
python
- Acumulación de Mantenimiento: Estrategias Efectivas para Resolverla
- Probadores de Válvulas de Vacío: Guía Completa para Entenderlos
- Descubra su clave de seguridad de red: pasos fáciles para encontrar y proteger su Wi‑Fi
- Llamadas WiFi explicadas: cómo funcionan y por qué importan
- Explorando 6G: El Futuro de la Conectividad Ultra-Rápida
- Entender las pruebas de descargas parciales: Protección de equipos de alta tensión
- Prevenga la cavitación en bombas: causas, síntomas y soluciones efectivas
- Brasado de cobre explicado: Técnicas y consejos para uniones fuertes y fiables
- Guía Experta: Instalación de Niveladores de Muelle (Dock Levelers) para Máxima Eficiencia
- Cómo instalar WordPress en Google Cloud: guía paso a paso
- Framework de Automatización de Pruebas UI Codificadas: Guía Completa para Principiantes