tane/docs/design/testing.md
2026-07-07 13:20:00 +02:00

40 lines
3.3 KiB
Markdown

# Tanemaki — Estrategia de pruebas (casi-TDD, sin depender de pruebas manuales)
*Convención del proyecto. Objetivo: **cada comportamiento cubierto por una prueba automática**; las pruebas manuales son la excepción, no la red de seguridad.*
## Principio
**Casi-TDD.** Para lógica nueva: test primero (red → green → refactor). Como mínimo innegociable: **ninguna rama se mergea sin tests que cubran lo nuevo.** La "definición de hecho" de cada historia **incluye sus tests**; sin tests, no está hecha. CI en cada push bloquea si algo falla o baja la cobertura.
`commons_core` es **Dart puro (sin Flutter)** → la lógica difícil (CRDT, identidad/derivación, cifrado, backup, pledge/WoT) se hace con TDD cómodo y rápido.
## La pirámide (Flutter/Dart)
- **Unit** (`dart test` / `flutter test`): lógica pura — CRDT, `Quantity`, derivación de claves, serialización, repositorios. Rápidos; el grueso vive en `commons_core`.
- **Widget** (`flutter_test`, `pumpWidget`): pantallas y componentes — interacción, *progressive disclosure*, i18n, accesibilidad (targets grandes).
- **Integration** (`integration_test` + `flutter test`): app entera en emulador/dispositivo, con **BD real cifrada (SQLCipher)**. Flujos e2e — **esto es lo que sustituye a las pruebas manuales.**
- **Golden** (regresión visual): pantallas clave; vigila que la accesibilidad no se rompa.
- **Migration** (Drift): `drift_dev schema generate` + `validateDatabaseSchema` por cada `schemaVersion`.
## Tests que este proyecto necesita sí o sí
- **Cifrado en reposo:** abrir el fichero de BD **en crudo** y afirmar que **NO hay texto en claro** (buscar una etiqueta conocida en los bytes y exigir ausencia). Regresión de seguridad clave para el "peor caso legal".
- **CRDT — convergencia:** *property-based* — fusionar operaciones en **cualquier orden** converge al mismo estado (LWW, OR-Set, log append-only, tombstones).
- **Migraciones:** cada versión migra desde la anterior y valida contra el esquema fresco.
- **Backup round-trip:** exportar → borrar → importar → **estado idéntico** (y cifrado).
- **Identidad:** derivación secp256k1 **determinista** desde la semilla (mismo input → misma clave) y unidireccional.
- **i18n:** ninguna cadena hardcodeada (lint), y todas las locales con las mismas claves.
## Lo difícil de automatizar (y cómo)
Cámara, keystore/biométrico, relays reales: **abstraer tras interfaces** y probar con *fakes/mocks*; dejar una capa fina de adaptadores de plataforma con un *smoke test* mínimo. Los *integration tests* en dispositivo cubren la integración real de la BD cifrada. Objetivo: **manual ≈ 0**.
## CI y cobertura
- CI en cada push/PR (Forgejo/Codeberg Actions o GitHub Actions): `flutter analyze` + unit + widget + **integration en emulador** + cobertura (lcov). **Merge bloqueado** si falla o baja la cobertura.
- Objetivo de cobertura **alto en `commons_core`** (p.ej. ≥ 85%); la UI, con widget + golden.
- Tests deterministas y rápidos: sin red real, reloj/UUID/HLC inyectables (para reproducibilidad).
## Flujo de trabajo
Dominio (`commons_core`): test primero. UI: al menos un widget test por pantalla/flujo antes de darla por terminada, y un *integration test* por flujo crítico (alta de semilla → persiste cifrada → reabrir → sigue ahí). Regla dura repetida: **sin tests, no se mergea.**