Saltar a contenido

Testing

Comandos

pytest                                  # Todos
pytest -x                               # Stop on first failure
pytest -k "test_create"                # Por nombre
pytest tests/unit/core/ --tb=short     # Solo core
pytest -m "not slow"                   # Excluir OCR/NER lentos
pytest --cov=src --cov-report=html     # Coverage
pytest tests/integration/ -vvs --pdb   # Debug interactivo

Markers

pytest -m "not slow"         # Excluir OCR/NER lentos
pytest -m integration        # Solo con BD
pytest -m e2e               # Flujo completo (playwright)

Estructura

tests/
├── unit/                    # Tests aislados (core, application, infrastructure)
│   └── interfaces/api/     # Tests API (FastAPI TestClient)
│       ├── test_api_foundation.py    # S24: 19 tests (health, auth, documents)
│       ├── test_api_fase2.py         # S25: 18 tests (process, validate, search, duplicates, config)
│       └── test_api_sprint25_1.py    # S25.1: 33 tests (security, XSS, JWT, bugs)
├── integration/             # Tests entre capas
├── e2e/                     # Flujo completo (playwright)
├── fixtures/                # Datos de test
└── conftest.py              # Fixtures pytest globales

Pre-commit (quality gate obligatorio)

ruff check src/ && mypy src/ && pytest tests/unit/ -x

Integration Tests

Ubicación: tests/integration/

Tests cross-layer que verifican la integración real entre capas (API → Application → Persistence):

pytest tests/integration/ -v -m integration    # Ejecutar solo integration
pytest tests/integration/ -vvs --pdb           # Debug interactivo

Fixtures (tests/integration/conftest.py): - real_container: ServiceContainer con BD SQLite en memoria (sin mocks) - real_client: TestClient de FastAPI conectado al container real - seeded_db: BD con datos de prueba pre-insertados - Fixture de auth con JWT real para endpoints protegidos

Cobertura: 9+ tests cross-layer verificando flujos completos (create → read → update → delete).

Tests CLI

El CLI cuenta con 68+ tests en tests/unit/interfaces/test_cli.py, cubriendo los 20 comandos disponibles incluyendo paths de éxito, error y validación de argumentos.

Metricas actuales

  • 1707 tests pasando (unit + integration + e2e + security + API)
  • 87.77% coverage (CI gate: 88%, excluyendo GUI)
  • 16 integration tests (9 API vertical slices + 7 pipeline)
  • 19 tests de seguridad base + 33 tests API security (S25.1)
  • E2E con playwright (29/32 estables)
  • 41 tests Fase 0 (Result pattern, frozen DTOs, JSON serialization)
  • 15 tests ServiceContainer Fase 0 (lazy loading, DI, thread safety)
  • 84 tests API total (19 S24 + 18 S25 + 33 S25.1 + 14 S28)

Tests Sprint 28 (nuevos)

Archivo Tests Cobertura
tests/integration/test_pipeline_integration.py 7 Pipeline OCR→NER→Dedup→Persist con mocks
tests/unit/interfaces/test_cli.py (expandido) +15 cmd_process, cmd_extract_acta, cmd_audit_report, cmd_health, cmd_stats_daily
tests/unit/persistence/test_sqlite_repository.py (expandido) +19 Range queries, transactions, find_by_field, context manager
tests/unit/interfaces/api/test_api_sprint28.py 14 Duplicates, import_export, auth refresh, config routes
tests/unit/test_coverage_sprint28.py 90 ServiceContainer, active_learning, auth JWT, sanitizers, statistics, dedup_config, main.py

Tests API (FastAPI TestClient)

Pattern para tests API:

# Fixture con auth desactivado y mocks
@pytest.fixture
def client(mock_container, test_settings, task_manager) -> TestClient:
    app = create_app()
    app.state.container = mock_container
    app.state.settings = test_settings
    app.state.task_manager = task_manager
    with patch("...dependencies.get_settings", return_value=test_settings):
        yield TestClient(app, raise_server_exceptions=False)

# Test usa client fixture
def test_endpoint(self, client):
    response = client.get("/api/v1/health")
    assert response.status_code == 200

Nota: ServiceContainer tests usan type(svc).__name__ == "ClassName" en vez de isinstance() para evitar problemas de import path en pytest.

Desglose tests application/

Archivo Tests Scope
test_statistics_service.py 16 8 base B3 + 8 Fase 0 I1
test_search_service.py 28 19 base B2 + 9 Fase 0 I2
test_validation_service.py 26 14 base B1 + 7 I3 + 5 I5
test_manual_entry_service.py 27 10 base B4 + 7 I4 + 5 I6 + 5 dedup
test_service_container.py 36 21 base + 15 Fase 0 properties
test_process_document.py 18 Pipeline OCR+NER+Dedup
test_export_excel.py 41 Export Excel use case
test_import_excel.py 42 Import Excel use case

Patron de tests Fase 0 (replicar para Fase 1+)

Cada servicio *_result() debe tener: - Test Success path con mock repository - Test Failure path con excepcion - Test FrozenInstanceError en Response DTO - Test dataclasses.asdict() + json.dumps() (JSON serializable) - Test backward compat (metodo dict/list original intacto)

Ver TESTING_GUIDE.md para estrategia detallada.