Medir cobertura sirve para observar el estado actual del proyecto. Pero en equipos y proyectos con integración continua también suele interesar impedir que la cobertura baje por accidente.
En este tema vamos a configurar un mínimo de cobertura. Si el reporte queda por debajo de ese valor, el comando termina con error.
fail_under y --cov-fail-under para proteger un mínimo de cobertura.
Un mínimo de cobertura ayuda a detectar regresiones. Por ejemplo, si el proyecto suele estar en 85% y un cambio lo baja a 70%, conviene revisar qué ocurrió antes de integrar ese cambio.
El objetivo no es perseguir un número perfecto. El objetivo es evitar que zonas ya cubiertas se pierdan silenciosamente.
Con coverage.py puedes indicar el mínimo al generar el reporte:
python -m coverage run -m pytest
python -m coverage report --fail-under=80
Si la cobertura total es menor que 80%, el segundo comando falla.
Una salida posible es:
TOTAL 120 30 75%
Coverage failure: total of 75 is less than fail-under=80
Para no repetir el valor en cada comando, puedes configurarlo:
[tool.coverage.run]
source = ["src"]
branch = true
[tool.coverage.report]
show_missing = true
fail_under = 80
Luego basta con ejecutar:
python -m coverage run -m pytest
python -m coverage report
Coverage usará el mínimo definido en la configuración.
Con pytest-cov, puedes usar --cov-fail-under:
En Windows PowerShell:
$env:PYTHONPATH="src"
python -m pytest --cov=src --cov-report=term-missing --cov-fail-under=80
En Linux o macOS:
PYTHONPATH=src python -m pytest --cov=src --cov-report=term-missing --cov-fail-under=80
Si la cobertura queda por debajo del mínimo, pytest termina con código de error.
Cuando falla por cobertura, no significa que las pruebas hayan fallado por una aserción. Significa que el porcentaje total quedó por debajo del umbral.
En un flujo automatizado, eso es útil porque bloquea cambios que reducen cobertura más allá de lo aceptado.
El mensaje suele indicar algo como:
FAIL Required test coverage of 80% not reached. Total coverage: 76.25%
Un error común es elegir un mínimo irrealista. Si el proyecto hoy tiene 62%, configurar 95% solo hará que el chequeo falle siempre.
Una estrategia razonable:
Supongamos que el proyecto está en 72%. Podrías empezar así:
[tool.coverage.report]
fail_under = 70
Luego, cuando el proyecto mejore:
[tool.coverage.report]
fail_under = 75
Este enfoque protege avances sin convertir el número en una meta artificial.
Un mínimo global puede ocultar zonas críticas sin cubrir. Por ejemplo, un proyecto puede tener 90% total y aun así tener el módulo de pagos en 40%.
El mínimo global es una barrera básica, no un reemplazo del análisis por módulo. En el próximo tema veremos cómo priorizar zonas críticas.
Una configuración práctica para continuar el curso:
[tool.coverage.run]
source = ["src"]
branch = true
omit = [
"*/__init__.py",
]
[tool.coverage.report]
show_missing = true
precision = 2
fail_under = 80
Ajusta fail_under al estado real de tu proyecto.
En una integración continua, el comando puede ser:
python -m pytest --cov=src --cov-branch --cov-report=term-missing --cov-fail-under=80
Si el comando termina con error, la ejecución de CI falla y el cambio debe revisarse.
Si ya configuraste fail_under y branch en pyproject.toml, el comando puede simplificarse:
python -m pytest --cov --cov-report=term-missing
Cuando el mínimo falla, revisa el reporte antes de cambiar el umbral.
source u omit.En este tema configuramos un mínimo de cobertura con --fail-under, fail_under y --cov-fail-under. Esta regla ayuda a evitar que la cobertura baje sin que nadie lo note.
En el próximo tema vamos a analizar cobertura por módulo para priorizar zonas críticas del sistema.