Un porcentaje total de cobertura puede ocultar diferencias importantes entre módulos. Un proyecto puede tener buen promedio general y, al mismo tiempo, tener poca cobertura en una parte crítica.
En este tema vamos a leer el reporte por archivo y priorizar dónde agregar pruebas según riesgo, importancia y cantidad de código sin cubrir.
Ejecuta el reporte con líneas faltantes y cobertura de ramas.
En Windows PowerShell:
$env:PYTHONPATH="src"
python -m pytest --cov=src --cov-branch --cov-report=term-missing
En Linux o macOS:
PYTHONPATH=src python -m pytest --cov=src --cov-branch --cov-report=term-missing
Una salida posible es:
Name Stmts Miss Branch BrPart Cover Missing
---------------------------------------------------------------------
src\tienda\carrito.py 25 2 8 1 88% 27, 35
src\tienda\cupones.py 22 0 10 0 100%
src\tienda\pagos.py 40 16 14 5 59% 12-18, 26, 31-38
src\tienda\tarifas.py 17 0 12 0 100%
---------------------------------------------------------------------
TOTAL 104 18 44 6 80%
El total es útil, pero la decisión importante está en las filas por archivo.
En el ejemplo, el total es 80%. Ese número puede parecer aceptable, pero src\tienda\pagos.py está en 59%.
Si pagos.py contiene reglas de cobro, validaciones de importes o decisiones de aprobación, probablemente sea más urgente que un módulo auxiliar con porcentaje menor pero poco riesgo.
No todos los módulos tienen la misma importancia. Para priorizar, considera:
Una forma práctica es combinar cobertura y criticidad:
Módulo Cobertura Criticidad Prioridad
---------------------------------------------------------
pagos.py 59% alta alta
carrito.py 88% media media
cupones.py 100% media baja
tarifas.py 100% baja baja
Esta tabla evita decidir solo por porcentaje. Un módulo crítico al 75% puede merecer atención antes que un módulo poco usado al 40%.
Supongamos que pagos.py contiene:
def autorizar_pago(monto, metodo, intentos_fallidos):
if monto <= 0:
raise ValueError("El monto debe ser mayor que cero")
if intentos_fallidos >= 3:
return "bloqueado"
if metodo == "tarjeta":
if monto > 100000:
return "revision"
return "aprobado"
if metodo == "transferencia":
return "pendiente"
return "rechazado"
Un reporte con líneas faltantes en este módulo merece atención porque cada rama representa una decisión importante.
Para mejorar cobertura de un módulo crítico, no empieces por líneas sueltas. Agrupa las pruebas por comportamiento:
import pytest
from tienda.pagos import autorizar_pago
def test_autorizar_pago_rechaza_monto_invalido():
with pytest.raises(ValueError):
autorizar_pago(0, "tarjeta", 0)
def test_autorizar_pago_bloquea_por_intentos_fallidos():
assert autorizar_pago(1000, "tarjeta", 3) == "bloqueado"
def test_autorizar_pago_tarjeta_monto_alto_requiere_revision():
assert autorizar_pago(150000, "tarjeta", 0) == "revision"
Estas pruebas suben cobertura y, más importante, verifican reglas relevantes.
Luego agrega casos para los demás caminos de negocio:
def test_autorizar_pago_tarjeta_monto_normal_aprueba():
assert autorizar_pago(5000, "tarjeta", 0) == "aprobado"
def test_autorizar_pago_transferencia_queda_pendiente():
assert autorizar_pago(5000, "transferencia", 0) == "pendiente"
def test_autorizar_pago_metodo_desconocido_rechaza():
assert autorizar_pago(5000, "cripto", 0) == "rechazado"
El reporte debería mejorar, pero el criterio principal sigue siendo cubrir decisiones reales del módulo.
Mientras trabajas sobre un módulo específico, puedes filtrar el reporte visualmente o ejecutar pruebas enfocadas. Por ejemplo:
python -m pytest tests/test_pagos.py --cov=src --cov-branch --cov-report=term-missing
Esto no cambia el criterio final del proyecto, pero acelera el ciclo mientras mejoras una zona concreta.
El reporte HTML ayuda a inspeccionar un módulo crítico con más contexto:
python -m pytest --cov=src --cov-branch --cov-report=html
Abre htmlcov/index.html y entra al archivo con baja cobertura. Revisa qué líneas faltan y qué ramas parciales aparecen.
Un archivo pequeño de utilidades internas puede tener baja cobertura, pero si casi no se usa o no contiene reglas importantes, quizá no sea la primera prioridad.
La cobertura debe orientar el trabajo. No debe reemplazar una decisión técnica sobre riesgo, impacto y valor de las pruebas.
Cuando un equipo decide priorizar ciertos módulos, conviene dejarlo explícito. Por ejemplo:
En este tema usamos la cobertura por módulo para decidir dónde enfocar el esfuerzo. El porcentaje total sirve como señal general, pero la priorización real surge al cruzar cobertura, criticidad y comportamiento.
En el próximo tema vamos a combinar resultados de cobertura de varias ejecuciones.