Taller práctico de Test-Driven Development (TDD) con Python.
- Aprender y practicar el ciclo Red-Green-Refactor
- Dominar pytest para testing en Python
- Aplicar TDD en ejercicios progresivos
- Integrar buenas prácticas de desarrollo
- Python 3.12
- UV (gestor de dependencias)
curl -LsSf https://astral.sh/uv/install.sh | shcd tdd_workshop
uv syncuv sync --devuv run pre-commit install
uv run pre-commit install --hook-type pre-push# Todos los tests
uv run pytest
# Tests específicos
uv run pytest tests/test_ejemplo.py
# Con coverage
uv run pytest --cov=srctdd_workshop/
├── src/ # Código fuente
└── tests/ # Tests
- Red: Escribir un test que falle
- Green: Escribir el código mínimo para pasar el test
- Refactor: Mejorar el código manteniendo los tests en verde
# Formatear código
uv run black src tests
# Ordenar imports
uv run isort src tests
# Ejecutar hooks manualmente
uv run pre-commit run --all-filesLos ejercicios se irán añadiendo progresivamente durante el taller.
/src/grading_system.py
/src/grading_system_no_tdd.py
| Aspecto | Sin TDD | Con TDD |
|---|---|---|
| Líneas de código | ~40 | ~15 |
| Complejidad | Alta | Baja |
| Tests escritos | 0 (o después) | 14 (primero) |
| Bugs conocidos | Desconocidos | 0 |
| Mantenibilidad | Difícil | Fácil |
| Confianza | Baja | Alta |
El ciclo TDD que evita esto:
Ciclo típico SIN TDD:
- Escribir código (con suposiciones)
- "Creo que funciona"
- Integrar
- Bug en producción
- "¿Por qué no lo testeamos antes?"
Ciclo con TDD (el que usaste):
- RED: Test falla → test_grade_score_sobresaliente()
- GREEN: Código mínimo → if score >= 9.0: grade = "Sobresaliente"
- REFACTOR: Mejorar sin romper tests
- Repetir
- Código simple, testeado y funcional
Ejemplo real del proyecto:
La función grade_score tiene 14 tests que cubren:
- Cada categoría de calificación
- Límites entre categorías (edge cases)
- Nota mínima (0.0)
- Nota máxima (10.0)
- Estado de aprobado/desaprobado
Sin TDD: Probablemente habrías olvidado testear:
- El límite de 4.99 (Insuficiente)
- El límite exacto de 5.0 (aprobado justo)
- El límite exacto de 9.0 (Sobresaliente)
Sin TDD:
- Código complejo "por si acaso"
- Features no solicitadas
- Bugs ocultos
- Difícil de cambiar
Con TDD:
- Código simple y directo
- Solo lo necesario
- Bugs detectados inmediatamente
- Fácil de cambiar (refactoring seguro)
TDD te fuerza a escribir código simple que resuelve el problema real, no el problema imaginario.
Instalamos un paquete adicional si no está ya incluido en las dependencias de desarrollo:
uv add --dev pytest-covEjecutamos los tests (con "uv run" si el entorno virtual no está activado y sin ello si está activado) con la opción de cobertura:
uv run pytest --cov=srcEstá incluida la modificación también en .pre-commit-config.yaml para que se ejecute automáticamente antes de cada push:
- repo: local
hooks:
- id: run-tests
name: Launch tests using pytest before push
entry: bash -c "PYTHONPATH=. uv run pytest --tb=short -v --cov=src --cov-report=term-missing"
language: system
pass_filenames: false
stages: [ pre-push ]
always_run: true
verbose: true