La Integración Continua (CI) es una práctica fundamental en el desarrollo de software moderno.
Su propósito es validar automáticamente cada cambio al código mediante la ejecución de pruebas
y controles de calidad antes de que dichos cambios sean integrados en la rama principal.
En este artículo se describe, paso a paso, cómo implementar un pipeline de CI funcional utilizando
GitHub Actions y pytest, incluyendo un umbral mínimo de cobertura de código
y la protección de la rama principal del repositorio.
Objetivo
Al finalizar este tutorial, el repositorio contará con:
- Ejecución automática de pruebas en cada Pull Request
- Validación de cobertura de código mínima
- Protección de la rama
mainmediante reglas del repositorio - Bloqueo automático de merges cuando las validaciones fallan
- Un pipeline de CI reproducible y mantenible
Tecnologías utilizadas
- Python 3.11
- pytest
- pytest-cov
- GitHub Actions
Estructura del proyecto
qa-ci-cd-lab/
│
├── src/
│ └── qa_ci_cd_lab/
│ ├── __init__.py
│ └── calculator.py
│
├── tests/
│ └── test_calculator.py
│
├── requirements.txt
├── pyproject.toml
└── .github/workflows/ci.yml
Creación del workflow de CI
GitHub Actions permite definir pipelines mediante archivos YAML almacenados en el repositorio.
Para este proyecto se creó el siguiente workflow:
Ruta del archivo:
.github/workflows/ci.yml
Contenido:
name: CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test:
name: pytest
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
run: |
PYTHONPATH=src pytest -q
Este workflow se ejecuta automáticamente ante cada push o pull_request
dirigido a la rama main.
Incorporación de cobertura de código
Para medir la cobertura de pruebas se utilizó el plugin pytest-cov.
Dependencias
En el archivo requirements.txt:
pytest
pytest-cov
Ejecución local
Antes de integrar la validación al pipeline, se recomienda ejecutarla localmente:
PYTHONPATH=src pytest \
--cov=qa_ci_cd_lab \
--cov-report=term-missing \
--cov-fail-under=80
El parámetro --cov-fail-under=80 define un umbral mínimo del 80% de cobertura.
Aplicación del quality gate en CI
El workflow se actualiza para incluir la validación de cobertura:
- name: Run tests with coverage
run: |
PYTHONPATH=src pytest \
--cov=qa_ci_cd_lab \
--cov-report=term-missing \
--cov-fail-under=80
Con esta configuración, el pipeline falla automáticamente si:
- Alguna prueba falla
- La cobertura de código es inferior al umbral definido
Protección de la rama principal
Para evitar integraciones directas sin validación, se configuró un ruleset sobre la rama
main con las siguientes reglas:
- Requerir Pull Request antes de hacer merge
- Requerir que los status checks pasen correctamente
- Bloquear force pushes
- Restringir eliminaciones de la rama
El status check seleccionado corresponde al workflow de CI definido previamente.
Validación del flujo
Para verificar el correcto funcionamiento del pipeline se realizó la siguiente prueba:
- Crear un Pull Request que introduce un cambio sin cobertura
- Ejecutar el pipeline automáticamente
- Confirmar que el merge queda bloqueado cuando el coverage es insuficiente
Este comportamiento confirma que el quality gate está funcionando según lo esperado.
Indicador visual del estado del CI
De manera opcional, se puede incluir un badge de estado en el README:

Consideraciones finales
La implementación de CI no depende del tamaño del proyecto, sino de la necesidad de mantener
un flujo de integración confiable y predecible. Automatizar pruebas y validaciones reduce riesgos,
facilita la colaboración y establece una base sólida para prácticas más avanzadas de entrega continua.
Repositorio de referencia
El código completo utilizado en este artículo se encuentra disponible en:
https://github.com/CFontalvo/qa-ci-cd-lab
Próximo artículo
Generación de reportes de pruebas y publicación de artifacts en CI

