Instalación de Coverage.py
pip install coverage

Ejecutar tests con cobertura
# Ejecutar tests recopilando datos de cobertura
coverage run --source='.' manage.py test
# Solo para la aplicación específica
coverage run --source='catalogo,usuarios' manage.py test
# Ver resumen en consola
coverage report
# Generar informe HTML detallado
coverage html
# Abrir el informe
# htmlcov/index.html
Ejemplo de salida de coverage report:
Name Stmts Miss Cover
---------------------------------------------
catalogo/admin.py 45 5 89%
catalogo/forms.py 38 3 92%
catalogo/models.py 67 8 88%
catalogo/views.py 89 21 76%
catalogo/serializers.py 34 2 94%
---------------------------------------------
TOTAL 273 39 86%
Configuración .coveragerc
Crea un archivo .coveragerc en la raíz del proyecto para configurar Coverage.py:
# .coveragerc
[run]
source = .
omit =
*/migrations/*
*/tests/*
*/test_*.py
*_test.py
manage.py
*/settings/*.py
*/wsgi.py
*/asgi.py
venv/*
.venv/*
[report]
exclude_lines =
pragma: no cover
def __repr__
if settings.DEBUG
raise NotImplementedError
if TYPE_CHECKING:
pass
show_missing = True
skip_covered = False
precision = 2
[html]
directory = htmlcov
title = Informe de cobertura - MiProyecto
[paths]
source =
.
Umbrales mínimos de cobertura
# Fallar si la cobertura está por debajo del 80%
coverage report --fail-under=80
pytest con pytest-django y pytest-cov
Muchos proyectos prefieren pytest sobre unittest. Con pytest-django y pytest-cov:
pip install pytest pytest-django pytest-cov
# pytest.ini o setup.cfg
[pytest]
DJANGO_SETTINGS_MODULE = mi_proyecto.settings.test
python_files = tests.py test_*.py *_tests.py
addopts = --cov=. --cov-report=html --cov-fail-under=80
# Ejecutar tests con cobertura
pytest
# Solo algunos tests
pytest catalogo/tests/ -v
# Con informe en consola
pytest --cov=catalogo --cov-report=term-missing
Integración en GitHub Actions CI/CD
# .github/workflows/tests.yml
name: Tests y cobertura
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
steps:
- uses: actions/checkout@v4
- name: Configurar Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Instalar dependencias
run: pip install -r requirements.txt
- name: Ejecutar migraciones
run: python manage.py migrate
env:
DATABASE_URL: postgresql://postgres:postgres@localhost/test_db
- name: Tests con cobertura
run: coverage run manage.py test && coverage report --fail-under=80
env:
DATABASE_URL: postgresql://postgres:postgres@localhost/test_db
- name: Subir informe de cobertura
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
Excluir código de la cobertura
Para líneas que son difíciles de testar (entornos específicos, código de fallback):
def configurar_logging(): # pragma: no cover
"""Solo se ejecuta en producción."""
import logging
logging.basicConfig(level=logging.ERROR)
def debug_info():
if settings.DEBUG: # La rama False es difícil de testar en desarrollo
return {'debug': True}
return {} # pragma: no cover
Una cobertura del 80-90 % es un objetivo razonable para la mayoría de proyectos Django. Aspirar al 100 % puede resultar contraproducente si requiere tests frágiles que solo aumentan el número, no la calidad de las pruebas.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Instalar y configurar Coverage.py para medir la cobertura del código Django. Ejecutar tests con coverage para recopilar datos de cobertura. Generar informes HTML detallados con coverage html. Configurar .coveragerc para excluir archivos irrelevantes. Integrar coverage en un pipeline CI/CD con umbrales mínimos.