Una suite automatizada no termina cuando las pruebas pasan. Con el tiempo, las pruebas deben mantenerse: nombres, datos, fixtures, estructura, tiempos de ejecución y confiabilidad.
En este tema veremos criterios prácticos para mantener pruebas legibles y confiables antes de avanzar al caso integrador.
Mantener una suite implica revisar que las pruebas sigan aportando valor. No basta con que existan muchos archivos de prueba.
Una suite mantenible debe ser:
Revisa la suite si aparecen estas señales:
test_1 o test_ok.Una prueba difícil de entender:
def test_1():
assert validar_cupon("DESC10") is True
Versión mantenible:
def test_validar_cupon_con_codigo_correcto_devuelve_true():
assert validar_cupon("DESC10") is True
El nombre debe explicar qué comportamiento se verifica.
Una prueba con demasiadas ideas es más difícil de diagnosticar:
def test_usuario():
usuario = crear_usuario()
assert usuario_esta_activo(usuario) is True
assert obtener_email(usuario) == "ana@example.com"
assert usuario["nombre"] == "Ana"
Puede dividirse en pruebas más enfocadas:
def test_usuario_esta_activo_con_usuario_valido_devuelve_true(usuario_valido):
assert usuario_esta_activo(usuario_valido) is True
def test_obtener_email_con_usuario_valido_devuelve_email_normalizado(usuario_valido):
assert obtener_email(usuario_valido) == "ana@example.com"
Si repites el mismo diccionario en muchas pruebas, considera una fixture o factory.
Datos duplicados:
usuario = {
"nombre": "Ana",
"email": "ana@example.com",
"activo": True,
}
Factory reutilizable:
def crear_usuario(**overrides):
usuario = {
"nombre": "Ana",
"email": "ana@example.com",
"activo": True,
}
usuario.update(overrides)
return usuario
Una fixture debe tener un propósito claro. Si una fixture prepara demasiadas cosas, puede ocultar información importante.
Preguntas útiles:
conftest.py no debe convertirse en un depósito de todo. Úsalo para fixtures compartidas, no para cualquier función auxiliar.
Si una construcción crece, muévela a tests/helpers y deja en conftest.py solo la fixture que la expone.
Los archivos de tests/data también requieren mantenimiento.
Los marcadores deben representar categorías útiles. Si hay demasiados, pierden valor.
Revisa:
lento?Ejecuta:
python -m pytest --durations=10
Si una prueba aparece siempre entre las más lentas, revisa si puede optimizarse, marcarse como lento o separarse en otra suite.
Una prueba confiable debe fallar por una causa real. Revisa pruebas que:
time.sleep.Los comandos principales deben estar documentados y funcionar:
python run_tests.py completa
python run_tests.py rapida
python run_tests.py critica
python run_tests.py reporte
Si un comando queda obsoleto, actualiza el script o el README.
Los reportes deben generarse en reports u otra carpeta clara. Evita mezclar reportes con código o datos versionados.
Verifica:
reports/ está en .gitignore si corresponde.Agrega al README.md una checklist:
## Checklist de mantenimiento de pruebas
- Los nombres de pruebas describen comportamiento.
- No hay datos duplicados innecesarios.
- Las fixtures tienen nombres claros.
- conftest.py no contiene lógica excesiva.
- Los datos de tests/data tienen nombres claros.
- Las pruebas lentas están marcadas.
- La suite rápida funciona.
- Los reportes se generan en reports.
- La suite completa pasa con python -m pytest.
Refactorizar pruebas significa mejorar su estructura sin cambiar lo que verifican.
Ejemplos:
Después de refactorizar, ejecuta la suite completa.
No toda repetición merece una abstracción. Si extraer una fixture hace que la prueba sea más difícil de leer, tal vez conviene dejar el dato explícito.
La prioridad es claridad. La reutilización debe ayudar, no esconder el escenario.
Las pruebas deben verificar comportamientos observables. Evita acoplarlas demasiado a detalles internos que pueden cambiar sin afectar la funcionalidad.
Mejor probar:
assert calcular_total(productos) == 350
Que probar pasos internos que no forman parte del contrato de la función.
--durations y marcadores.Revisa tres archivos de prueba del proyecto y aplica al menos tres mejoras:
Ejemplo de mejora con parametrización e IDs:
import pytest
from app.cupones import validar_cupon
@pytest.mark.parametrize(
"cupon, esperado",
[
("DESC10", True),
("desc10", True),
("DESC20", False),
],
ids=["codigo_correcto", "minusculas", "codigo_incorrecto"],
)
def test_validar_cupon_devuelve_resultado_esperado(cupon, esperado):
assert validar_cupon(cupon) is esperado
Después de aplicar cambios:
python -m pytest
Antes de continuar con el caso integrador, verifica lo siguiente:
python -m pytest.En este tema revisamos cómo mantener pruebas automatizadas legibles y confiables. Una suite útil requiere atención continua: nombres claros, datos ordenados, fixtures simples y fallas fáciles de diagnosticar.
En el próximo tema construiremos un caso práctico integrador con una suite automatizada completa para un proyecto Python.