Entrega Incremental 2 - TDD, BDD y Cobertura
Esta evaluación REQUIERE la E1 (Dominio) completada. Debes tener el dominio funcionando para poder testearlo. Si tu E1 no funciona, no puedes hacer E2.
Estas clases preparan los conocimientos necesarios para esta evaluación:
Garantizar la calidad del dominio de TaskFlow mediante pruebas automatizadas con pytest (unitarios) y behave (BDD). Aplicar el ciclo TDD y alcanzar cobertura mínima del 80%.
Individual o en parejas (máximo 2 personas). Debe ser el mismo equipo de E1.
Formato de entrega: Repositorio GitHub con dominio de E1 + carpeta tests/ con todos los tests pytest + archivo .feature para behave. Incluir README.md con comando para ejecutar tests.
Descripción: Pruebas exhaustivas para todas las clases del dominio usando pytest.
test_usuario.py: Tests para clase Usuariotest_proyecto.py: Tests para clase Proyectotest_tarea.py: Tests para clase Tareatest_enums.py: Tests para enums PrioridadTarea y EstadoTarea@pytest.fixture para datos de prueba reutilizables@pytest.mark.parametrize para múltiples casospytest.raises() para probar erroresDescripción: Crear fixtures reutilizables para evitar duplicación de código en tests.
conftest.py:usuario_ejemplo(): Usuario válido para pruebasproyecto_ejemplo(usuario_ejemplo): Proyecto con lídertarea_ejemplo(): Tarea pendiente por defectoproyecto_con_tareas(proyecto_ejemplo, tarea_ejemplo): Proyecto pobladofunction (default): Para tests que modifican estadomodule: Para datos de solo lectura compartidosDescripción: Escenarios en lenguaje Gherkin que describen comportamiento del sistema.
features/usuarios.feature: Gestión de usuariosfeatures/proyectos.feature: Gestión de proyectosfeatures/tareas.feature: Gestión de tareasGiven, When, Then correctamenteBackground para contexto comúnScenario Outline con ExamplesDescripción: Medir y reportar cobertura de pruebas con pytest-cov.
pytest --cov=src --cov-report=html --cov-report=termimport pytest
from datetime import datetime
from src.domain.usuario import Usuario
from src.domain.proyecto import Proyecto
from src.domain.tarea import Tarea, PrioridadTarea, EstadoTarea
@pytest.fixture
def usuario_ejemplo() -> Usuario:
"""Fixture que provee un usuario válido para pruebas."""
return Usuario(
username="testuser",
email="test@example.com",
nombre_completo="Usuario de Prueba"
)
@pytest.fixture
def proyecto_ejemplo(usuario_ejemplo: Usuario) -> Proyecto:
"""Fixture que provee un proyecto con líder."""
return Proyecto(
nombre="Proyecto Test",
descripcion="Descripción de prueba",
lider=usuario_ejemplo
)
@pytest.fixture
def tarea_ejemplo() -> Tarea:
"""Fixture que provee una tarea pendiente."""
return Tarea(
titulo="Tarea de prueba",
descripcion="Descripción de prueba",
prioridad=PrioridadTarea.MEDIA
)
import pytest
from src.domain.usuario import Usuario
class TestUsuarioCreacion:
"""Tests para la creación de usuarios."""
def test_crear_usuario_valido(self, usuario_ejemplo: Usuario):
"""Verifica que un usuario válido se crea correctamente."""
assert usuario_ejemplo.username == "testuser"
assert usuario_ejemplo.email == "test@example.com"
assert usuario_ejemplo.activo is True
@pytest.mark.parametrize("username_invalido,expected_msg", [
("ab", "al menos 3 caracteres"),
("user@name", "solo letras y números"),
("", "al menos 3 caracteres"),
])
def test_username_invalido_lanza_error(
self, username_invalido: str, expected_msg: str
):
"""Verifica que usernames inválidos lanzan ValueError."""
with pytest.raises(ValueError) as exc_info:
Usuario(username=username_invalido, email="test@test.com")
assert expected_msg in str(exc_info.value)
def test_email_invalido_lanza_error(self):
"""Verifica que emails sin @ lanzan ValueError."""
with pytest.raises(ValueError, match="Email inválido"):
Usuario(username="testuser", email="emailinvalido.com")
Instalar pytest, pytest-cov, behave y crear pytest.ini
Usuario, proyecto, tarea y combinaciones
Creación, validaciones, activar/desactivar con parametrize
Estados, prioridades, completar
Agregar tareas, filtrar, relaciones
Archivos .feature y steps correspondientes
Ejecutar pytest --cov y ajustar hasta alcanzar
| Criterio | Excelente (5.0) | Aceptable (3.5) | Insuficiente | Peso |
|---|---|---|---|---|
| Cobertura ≥80% | ≥80% con tests significativos que prueban lógica real | 70-79% o tests superficiales | <70% o sin medir cobertura | 30% |
| Tests Unitarios | Fixtures, parametrize, raises, setup/teardown bien usados | Tests básicos sin técnicas avanzadas | Sin pytest o tests vacíos | 25% |
| Tests BDD | 3+ escenarios Gherkin claros, steps implementados | Escenarios básicos o pasos incompletos | Sin behave o .feature vacíos | 20% |
| Integración E1 | Tests pasan contra dominio real de E1 | Algunos tests fallan por dominio incompleto | Dominio E1 no funciona | 15% |
| Documentación | README con comandos, requisitos, cobertura | README básico sin instrucciones claras | Sin README o vacío | 10% |
El dominio testeado aquí se expondrá vía web en E3: Prototipo Web. Asegúrate de que todos los tests pasen antes de continuar.