18. Archivos que no conviene medir: pruebas, scripts auxiliares y código generado

18.1 Objetivo del tema

Un reporte de cobertura es útil cuando mide el código correcto. Si incluye pruebas, archivos generados o scripts manuales, el porcentaje puede volverse confuso.

En este tema vamos a definir criterios para decidir qué archivos medir y cuáles dejar fuera del reporte.

Objetivo práctico: configurar coverage para enfocarse en el código de aplicación y evitar ruido en el reporte.

18.2 Qué debería medir la cobertura

La cobertura suele medir el código que queremos proteger con pruebas automatizadas: módulos de dominio, validaciones, servicios, funciones puras, clases y reglas de negocio.

En el proyecto del curso, eso corresponde principalmente a:

src/
`-- tienda/
    |-- tarifas.py
    |-- cupones.py
    |-- carrito.py
    `-- ...

Los tests ejecutan ese código, pero no suelen ser el objetivo principal del porcentaje de cobertura.

18.3 Por qué no medir tests

Si coverage mide tests, el porcentaje total puede subir o bajar por razones poco útiles. Los tests son importantes, pero medir su propia cobertura no responde la pregunta principal.

La pregunta que nos interesa es:

¿Qué parte del código de aplicación fue ejecutada por las pruebas?

Por eso conviene configurar source = ["src"] o usar --cov=src.

18.4 Configurar source

En pyproject.toml:

[tool.coverage.run]
source = ["src"]
branch = true

Con esta configuración, coverage se concentra en el código de src.

Luego puedes ejecutar:

python -m coverage run -m pytest
python -m coverage report

18.5 Usar pytest-cov sin medir tests

Con pytest-cov, puedes indicar explícitamente qué medir:

En Windows PowerShell:

$env:PYTHONPATH="src"
python -m pytest --cov=src --cov-report=term-missing

En Linux o macOS:

PYTHONPATH=src python -m pytest --cov=src --cov-report=term-missing

Así los tests se ejecutan, pero el reporte se enfoca en src.

18.6 Scripts auxiliares

Un proyecto puede tener scripts para tareas manuales:

scripts/
|-- cargar_datos_demo.py
|-- limpiar_temporales.py
`-- generar_reporte_manual.py

No siempre conviene medirlos con la misma regla que el código de aplicación. Algunos se ejecutan manualmente, dependen de archivos locales o solo preparan datos de desarrollo.

Si no son parte del comportamiento principal, puedes excluirlos:

[tool.coverage.run]
source = ["src"]
omit = [
    "*/scripts/*",
]

18.7 Código generado

El código generado por herramientas no suele editarse a mano. Ejemplos habituales:

  • Migraciones generadas por frameworks.
  • Clientes generados desde un esquema o API.
  • Archivos creados por herramientas de build.
  • Reportes o artefactos temporales.

Si el archivo se regenera automáticamente, normalmente no tiene sentido perseguir cobertura línea por línea sobre él.

18.8 Excluir código generado

Un ejemplo de configuración:

[tool.coverage.run]
source = ["src"]
branch = true
omit = [
    "*/migrations/*",
    "*/generated/*",
    "*/_generated.py",
]

Los patrones deben ajustarse a la estructura real del proyecto. No copies exclusiones que no necesitas.

18.9 Archivos __init__.py

Muchos archivos __init__.py están vacíos o solo declaran el paquete. En esos casos, medirlos aporta poco.

omit = [
    "*/__init__.py",
]

Pero si un __init__.py contiene lógica real, no lo excluyas automáticamente. La regla depende del contenido.

18.10 No esconder código importante

Excluir archivos debe reducir ruido, no esconder problemas. Si un archivo contiene reglas de negocio, validaciones o lógica crítica, debería estar medido.

Una mala exclusión sería:

omit = [
    "src/tienda/pagos.py",
]

Si pagos.py contiene reglas importantes, excluirlo solo mejora el porcentaje en apariencia y empeora la utilidad del reporte.

18.11 Diferencia entre omit y pragma

omit excluye archivos completos o grupos de archivos. pragma: no cover excluye líneas o bloques puntuales.

  • Usa omit: para archivos generados, scripts auxiliares o carpetas completas que no forman parte de la medición.
  • Usa pragma: para una línea puntual dentro de un archivo que sí se mide.

18.12 Revisar el reporte después de configurar

Después de cambiar source u omit, ejecuta:

python -m coverage erase
python -m coverage run -m pytest
python -m coverage report

Revisa que aparezcan los archivos esperados y que no desaparezca código importante.

18.13 Relación con .gitignore

Los resultados generados por coverage no deberían versionarse:

.coverage
htmlcov/

Esto no afecta qué se mide. Solo evita subir al repositorio archivos generados localmente.

18.14 Problemas frecuentes

  • El reporte incluye tests: configura source = ["src"] o usa --cov=src.
  • Faltan archivos importantes: revisa patrones de omit demasiado amplios.
  • El porcentaje cambió mucho: probablemente ahora estás midiendo un conjunto distinto de archivos.
  • Se excluye código difícil de probar: considera refactorizar antes de omitir.

18.15 Conclusión

En este tema definimos qué archivos conviene medir y cuáles pueden quedar fuera del reporte. La configuración debe enfocar coverage en el código de aplicación sin ocultar lógica importante.

En el próximo tema vamos a configurar un mínimo de cobertura para que la ejecución falle cuando el porcentaje baje de lo esperado.