Ir al contenido

Estado de Tests y Plan de Hardening

Scope: DEVELOPMENT / localhost only. No production, no CI cloud, no deploy. The goal is a trustworthy, reproducible local test battery and a strong hardening roadmap up to (but not beyond) the dev boundary.

Status: iterative — this document is built and revised across sessions. Iteration 0 below is the verified baseline as of 2026-05-31.

Method: the verdicts below were produced by destroying the docker volumes and rebooting the stack cold from fixtures, then running the real suites — not by trusting cached state.


Iteration 0 — Verified baseline (2026-05-31, branch coveris-b-integration)

Sección titulada «Iteration 0 — Verified baseline (2026-05-31, branch coveris-b-integration)»
LayerVerdictOne-line
Backend (Django/DRF/pytest)🟢 HEALTHYCold boot clean from fixtures; 713 passed, 1 xfail, 0 failures in 2m13s.
Backend integration / contract🟢 HEALTHY-m api 286 passed, -m regression 60 passed; API.md↔test coverage guard in place.
Frontend build (Angular 21)🔴 BROKENbun run build fails — 2 TS errors in roster-detail.component.ts.
Frontend unit (Vitest)🔴 BLOCKED0 specs run — Angular compile halts before any spec executes. ~70 spec files, ~721 cases, all currently un-runnable.
Frontend static🟢 PASSbun run test:static — 1 file, 3 tests pass.
E2E (any layer)NONENo Playwright/e2e exists; deferred post-MVP per ADR-009-d.

The single blocking issue is the frontend build. Until it compiles, the entire 700+ case frontend suite is dark — we have no signal on the frontend, and the green backend number can give a false sense of overall health.

  • Cold boot: docker compose down -vbuildup -d reached healthy (~70s). Health verified inside the container via /api/health/.
  • Seed: fixtures auto-load in backend/entrypoint.sh (loaddata mock_clinic.yaml + mock_employees.yaml, migrated from 11 seed commands in commit e3bd1a2). Seeded 6 users, 31 employees. Idempotent (get_or_create superuser, loaddata overwrite).
  • Suite: 42 test files / 714 functions. pytest + pytest-django, config in backend/pyproject.toml (markers: slow, api, regression). Run in-container: docker compose exec -T api pytest -q.
  • Known/accepted gaps:
    • 1 xfail: test_login_throttle (DRF caches throttle scope at import; local sets rate None). Accepted per ADR-009-b.
    • KNOWN_UNTESTED allowlist: 57 endpoints documented in API.md but without contract tests — mostly CRUD detail/update/delete and the 12 Employee + 3 Assignment FSM transition endpoints. Guarded by tests/test_contract_coverage.py (fails if API.md drifts).
    • No Cognito auth tests (SimpleJWT only in dev — fine for localhost scope).
    • No coverage % enforced (pytest-cov available, not wired).
    • UnorderedObjectListWarning on Position querysets (cosmetic; missing default ordering).
  • Framework: Vitest 4 via Angular @angular/build:unit-test. Coverage threshold configured at 80% (vitest.config.ts) but never reached because the suite can’t run.
  • Blocking build errors — both in frontend/src/app/features/roster/roster-detail.component.ts:
    1. L342 TS2339: Property 'tagGridColumns' does not exist on type 'RosterDetail' — declared at L806 but not template-visible (likely private; templates need public/protected), or a stale reference.
    2. L344 TS2345: 'TagGridTag' is not assignable to 'ApiEmployeeTag'kdx-tag-grid’s (remove) output emits the display-only TagGridTag, but removeTag() (L1040) still expects the full ApiEmployeeTag. Types not kept in sync during the kdx-tag consolidation.
  • Root cause context: in-flight refactor on this branch — cv-tag + emp-tag components deleted and consolidated into kdx-tag/kdx-tag-grid; no-mock-imports.spec.ts rewritten to build-time glob scanning. The consolidation left roster-detail half-migrated.
  • 1 skipped test: login-card.component.spec.ts:52 it.skip(...) (error-message display) — undocumented skip.

Ordered by leverage. Each item is dev-local only. P0 = unblock signal; P1 = trust the signal; P2 = widen coverage; P3 = make it reproducible/enforced.

P0 — Unblock the frontend (nothing else is trustworthy until this is green)

Sección titulada «P0 — Unblock the frontend (nothing else is trustworthy until this is green)»
  1. Fix the two roster-detail.component.ts type errors (make tagGridColumns protected/public; reconcile TagGridTag vs ApiEmployeeTag in removeTag — adapt the handler or the emitted type).
  2. Re-run bun run build → must succeed.
  3. Re-run bun run test (non-watch) → establish the real frontend pass/fail baseline. Record it here as Iteration 1.
  4. Triage every spec broken by the kdx-tag consolidation; update or delete stale specs for the removed cv-tag/emp-tag.
  1. Resolve or formally document the login-card it.skip (fix or write the rationale inline).
  2. Add default ordering to Position querysets to kill UnorderedObjectListWarning (pagination determinism).
  3. Make the unit runner non-watch by default for scripted runs (a test:ci-style script using the run-once flag) so agents/Make never hang.
  4. Verify make test (backend + frontend) runs end-to-end green after P0.

P2 — Widen coverage (close the documented gaps)

Sección titulada «P2 — Widen coverage (close the documented gaps)»
  1. Backend: write contract tests for the highest-risk slice of the 57 KNOWN_UNTESTED endpoints — prioritize the 15 FSM transition endpoints (Employee ×12, Assignment ×3), then CRUD delete/update. Remove each from KNOWN_UNTESTED as it lands.
  2. Frontend: add specs for the Hours (features/hours/) feature — currently zero coverage.
  3. Wire pytest-cov and set a starting backend coverage floor (report-only first, then enforce).
  4. Enforce the existing 80% Vitest threshold once the suite runs (currently inert).

P3 — Reproducibility & enforcement (dev boundary)

Sección titulada «P3 — Reproducibility & enforcement (dev boundary)»
  1. A single make test-cold target: down -v → build → up → wait-for-health (in-container) → seed check → backend pytest → frontend test+build. One command proves the whole local battery from scratch.
  2. A pre-push / local git hook (or documented one-liner) that runs bun run build + both suites — catch baseline breakage like P0 before it’s committed.
  3. Document the canonical commands in one place (README/Makefile): bun run test (NOT bun test/bunx vitest), in-container pytest, health-check-inside-container.
  4. (Stretch, still dev-local) Stand up the deferred Playwright e2e skeleton (ADR-009-d) against the docker stack — smoke path: login → dashboard → roster.

Ventana de terminal
# Backend — cold, from repo root (authoritative health = inside container)
docker compose down -v && docker compose build && docker compose up -d
docker compose exec -T api python -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8000/api/health/',timeout=5).read().decode())"
docker compose exec -T api pytest -q # full suite
docker compose exec -T api pytest -m api -q # contract
docker compose exec -T api pytest -m regression -q # regression
# Frontend — from frontend/
bun run test # unit (ng test → Vitest); ensure non-watch for scripted runs
bun run test:static # static checks
bun run build # MUST pass — currently the blocker
# Wrappers
make test-backend | make test-frontend | make test | make clean (down -v)

  • 2026-05-31 — Iteration 0: Baseline captured via cold docker rebuild. Backend green (713/1xfail/0fail). Frontend build broken (roster-detail.component.ts ×2 TS errors) → unit suite fully blocked. Roadmap drafted.