Cobertura y Reportes
La cobertura mide qué líneas ejecutan tus pruebas. Revela ramas sin probar, no la calidad de las pruebas; úsala para encontrar brechas, no como una métrica de calidad por sí sola.
Receta
uv add --group dev pytest-cov
uv run pytest --cov=src --cov-report=term-missingCuándo usar esto:
- Identificar rutas de código sin probar antes del lanzamiento
- Forzar una cobertura mínima en CI
- Generar reportes HTML para revisión
Ejemplo de Trabajo
[tool.pytest.ini_options]
addopts = "--cov=src --cov-report=term-missing --cov-fail-under=80"
[tool.coverage.run]
source = ["src"]
branch = true
omit = ["*/tests/*", "*/__main__.py"]
[tool.coverage.report]
show_missing = true
skip_covered = falseuv run pytest
# Nombre Stmts Miss Branch BrPart Cover
# src/myapp/billing.py 42 3 12 2 91%uv run pytest --cov=src --cov-report=html
open htmlcov/index.htmlLo que esto demuestra:
--cov=srcmide el paquete instalado, no las pruebasbranch = truerastrea las rutas de if/else--cov-fail-under=80bloquea CI por debajo del umbral- El reporte HTML resalta las líneas no cubiertas en rojo
Análisis Profundo
Leyendo el Reporte
| Columna | Significado |
|---|---|
| Stmts | Sentencias ejecutables |
| Miss | Sentencias nunca ejecutadas |
| Branch | Ramas condicionales |
| BrPart | Ramas parcialmente cubiertas |
Lo que la Cobertura Omite
- Asertos correctos (100% de cobertura con pruebas incorrectas)
- Fallos de integración
- Errores de concurrencia
- Violaciones de contratos de API
Trampas Comunes
- Perseguir el 100% de cobertura - las pruebas no afirman nada significativo. Solución: objetivo del 80-90%; enfócate en las rutas críticas.
- Cobertura en
tests/- números inflados. Solución: solo--cov=src. - Sin cobertura de ramas - se omitieron ramas
else. Solución:branch = trueen la configuración de cobertura. - Puerta de cobertura sin revisión - se omitieron ramas importantes. Solución: emparejar el umbral con la revisión de PR de la salida
term-missing. - Código generado en la cobertura - objetivos imposibles. Solución:
omitmigraciones y archivos generados.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| testing de mutación (mutmut) | Auditoría de calidad de pruebas | Búsqueda rápida de brechas |
| diff-cover | Cobertura por ámbito de PR | Auditoría completa del proyecto |
| Ninguna herramienta de cobertura | Prototipo | Servicios de producción |
Preguntas Frecuentes
¿Cuál es un buen objetivo de cobertura?
El 80% es un suelo común. Módulos críticos (facturación, autenticación) deberían tener un porcentaje más alto.
¿La cobertura significa que las pruebas son buenas?
No. Solo muestra las líneas ejecutadas. Combina con revisión y testing de mutación.
¿Cómo excluyo líneas?
# pragma: no cover en código defensivamente inalcanzable.
¿Cómo veo las ramas no cubiertas?
--cov-report=term-missing con branch = true.
¿Puedo forzar la cobertura en CI?
--cov-fail-under=80 en las opciones adicionales de pytest.
¿Cómo hago la cobertura de un solo módulo?
pytest --cov=src/myapp/billing.
¿Qué es diff-cover?
Reporta la cobertura solo en las líneas cambiadas. Bueno para puertas de PR.
¿Reporte HTML o de terminal?
Terminal para CI. HTML para exploración local de brechas.
¿Cómo combino la cobertura de ejecuciones paralelas?
coverage combine y luego coverage report después de las ejecuciones de pytest-xdist.
¿Debería cubrir __init__.py?
Solo si contiene lógica. Los archivos __init__.py vacíos se omiten.
Relacionado
- Configuración de pytest - configuración de addopts
- Mejores Prácticas de Pruebas - política de cobertura
- Pruebas Basadas en Propiedades - cobertura de rutas más profunda
- Linting en CI/CD - puertas de CI
Versiones de la Pila: Esta página fue escrita para Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.