veza/docs/STRATEGIE_COUVERTURE_ET_TMT_2025_02.md
senke 8a0f008345 chore: playwright workflow, docs, rapports audit, visual-tests, tmt unit
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-11 22:19:34 +01:00

339 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# STRATÉGIE DE COUVERTURE & ORCHESTRATION TMT — VEZA
**Date** : 2025-02-10
**Mandat** : Architecte qualité — redressement de la base de tests
**Audits de référence** : AUDIT_TESTS_ET_COUVERTURE_2025_02.md, AUDIT_FRONTEND_EXHAUSTIF_2025_02.md
**Objectif** : *« Une régression significative ne peut plus passer inaperçue. »*
---
## 0. POSTURE
Décisions appliquées. Pas de pédagogie. Pas de généralités.
---
## 1. REDÉFINITION DE LA COUVERTURE
### 1.1 Définition opérationnelle
> **Couverture** = probabilité que le système se comporte correctement lorsqu'il est modifié.
Trois axes :
| Axe | Signification | Mesure |
|-----|---------------|--------|
| **Logique critique** | Auth, RBAC, commerce, upload, webhooks | Branches exercées sur chemins nominaux ET erreurs |
| **Branches d'erreur** | catch, retry, fallback, validation | % branches catch/error couvertes |
| **Contrats implicites** | API, auth, invariants métier | Tests contractuels, assertions sur schémas |
### 1.2 Cibles chiffrées (différenciées)
| Domaine | Cible branches | Cible lignes | Bloquant |
|---------|----------------|--------------|----------|
| **Auth / RBAC** | ≥ 90% | ≥ 85% | Oui |
| **Commerce / Marketplace** | ≥ 85% | ≥ 80% | Oui |
| **Upload / Tracks** | ≥ 85% | ≥ 80% | Oui |
| **Services API (client.ts, interceptors)** | ≥ 80% | ≥ 75% | Oui |
| **Handlers / Services Go critiques** | ≥ 90% | ≥ 85% | Oui |
| **Hooks / utils frontend** | ≥ 80% | ≥ 80% | Oui |
| **Logique utilitaire** | ≥ 80% | ≥ 80% | Non (warning) |
| **UI pure (composants)** | Indicateur | Indicateur | Non |
**Pourquoi un seuil global unique est architecturalement débile** :
Un seuil global (ex. 80%) masque les zones critiques sous-testées. Le client API (2238 lignes) peut être négligé tandis que des utils triviales gonflent le pourcentage. Les domaines à fort risque (auth, RBAC) doivent avoir des seuils plus élevés et être vérifiés séparément.
---
## 2. STRATÉGIE PAR COUCHE
### 2.1 Backend (Go)
**Fonctions critiques identifiées** (à couvrir en priorité) :
- `internal/core/auth/service.go` — ValidateSession, HasRole, HasPermission
- `internal/api/router.go` — Middleware auth, RBAC
- Handlers : auth, tracks, playlists, marketplace, webhooks
- `internal/database/` — Migrations, prepared statements (chemins erreur)
**Tests à écrire/corriger** :
| Type | Action | Justification |
|------|--------|---------------|
| Chemins nominaux | Corriger mocks auth middleware | Échec actuel : `0 out of 1 expectation(s) were met` |
| Erreurs métier | Ajouter tests sur erreurs 401, 403, 404 | RBAC non validé |
| Erreurs infra | Simuler DB down, timeout | Branches jamais exercées |
**Interdictions** :
- Mocks non alignés avec les interfaces réelles (signatures Go)
- Tests dépendants du timing (supprimer ou utiliser `testify/assert.Eventually`)
### 2.2 Frontend
| Couche | Rôle | Outil | Couverture |
|--------|------|-------|------------|
| **Unitaire** | Hooks, helpers, utils, services purs | Vitest | branches ≥ 80% sur `features/*`, `hooks`, `services` |
| **Intégration** | Pages, flows (MSW) | Vitest + MSW | Pas de logique métier significative non testée hors E2E |
| **E2E** | Flux critiques (auth, playlists, search) | Playwright | Smoke obligatoire |
**Objectif** : *Zéro logique métier significative non testée hors E2E.*
**Zones prioritaires** :
- `authStore` vs `AuthContext` — cohérence (réduire après unification auth)
- `client.ts` — découper puis tester interceptors, retry, offline queue
- `optimisticUpdates.ts` — rollback, invalidation
- `marketplaceService`, `webhookService` — peu couverts
### 2.3 Rust (Chat, Stream)
- **Clippy** : 0 warnings (déjà vital)
- **Tests** : Déjà dans TMT vital
- Pas de changement structurel prévu
---
## 3. ÉLIMINATION DES FAUX POSITIFS
| Élément | Action | Argument |
|---------|--------|----------|
| `npm run test -- --run \|\| true` | **Supprimer** | Tests qui passent malgré régression = illusion |
| Snapshots sans assertion sémantique | **Supprimer ou remplacer** | Snapshots décoratifs ; ajouter `expect` sur comportement |
| Tests qui ne testent que React/framework | **Supprimer** | Redondants avec tests framework |
| `PlaylistErrorBoundary.test.tsx` (jest.spyOn) | **Remplacer** par `vi.spyOn` | Incohérence Vitest |
| Tests Go auth/RBAC avec mocks cassés | **Réparer** | Sinon les exclure explicitement (documenté) |
---
## 4. RÉDUCTION DU MOCKING
**Objectif** : remplacer le mocking par de la **composition testable**.
| Action | Détail |
|--------|--------|
| Extraction de ports/adapters | Interfaces pour `authService`, `apiClient` — injection en tests |
| MSW ciblé | Garder MSW pour les handlers HTTP ; ne pas mocker 10+ modules par test |
| Doubles de test minimaux | Backend : interfaces Go déjà présentes ; utiliser des implémentations stub |
| Unifier auth | Une source (Store) → un mock au lieu de deux |
**Critère** : si un test nécessite > 5 mocks, le design est toxique.
---
## 5. ORCHESTRATION TMT
### 5.1 État actuel (diagnostic)
| Aspect | État | Détail |
|--------|------|--------|
| **TMT utilisé en CI** | ❌ Non | La CI n'appelle jamais `tmt run` |
| **Types de tests TMT** | Partiel | Build, bundle_size, build_perf, no_critical_js ; Go unit (internal) ; Rust clippy/test |
| **Vitest** | ❌ Hors TMT | Exécuté directement dans ci.yml avec `\|\| true` |
| **Playwright** | ❌ Hors TMT | Workflow séparé, sans `working-directory: apps/web` |
| **Contournement** | CI directe | `go test`, `npm run test`, `npx playwright test` sans TMT |
**Conclusion** : TMT est une couche déclarative sous-exploitée. La CI est une projection ad-hoc, pas fidèle à TMT.
### 5.2 Rôle cible de TMT
TMT devient :
- **Point d'entrée unique** pour tous les tests
- Garant de l'ordre, des dépendances, des profils (local / CI / nightly)
### 5.3 Modélisation TMT cible
```
tmt/
├── plans/
│ ├── vital.fmf # Tier 1 — bloque tout
│ ├── integration.fmf # Tier 2 — nécessite infra (DB, Redis)
│ └── nightly.fmf # Tier 3 — E2E, contract, visuels
├── tests/
│ ├── frontend/
│ │ ├── build.sh
│ │ ├── build_perf.sh
│ │ ├── bundle_size.sh
│ │ ├── no_critical_js.sh
│ │ └── unit.sh # NOUVEAU — npm run test -- --run
│ ├── frontend-e2e/
│ │ └── playwright.sh # NOUVEAU — npx playwright test
│ ├── backend/
│ │ ├── unit.sh
│ │ ├── integration.sh
│ │ ├── core_isolation.sh
│ │ ├── startup_time.sh
│ │ └── memory_budget.sh
│ └── services/
│ ├── rust_clippy.sh
│ └── rust_test.sh
└── README.md
```
**Variables d'environnement explicites** :
| Variable | Valeur | Rôle |
|----------|--------|------|
| `GOMAXPROCS` | 1 | Low-power backend |
| `LIBGL_ALWAYS_SOFTWARE` | 1 | GPU désactivé |
| `RUST_BACKTRACE` | 0 | Bruit minimisé |
| `VEZA_TEST_DB_URL` | (optionnel) | Intégration |
| `VEZA_E2E_API_URL` | (optionnel) | E2E |
**Artefacts de sortie** :
| Artefact | Emplacement | Usage |
|----------|-------------|-------|
| Coverage Go | `veza-backend-api/coverage.out` | Rapport, seuils |
| Coverage Vitest | `apps/web/coverage/` | Rapport, seuils |
| Playwright report | `apps/web/playwright-report/` | Debug E2E |
### 5.4 Plans TMT
| Plan | Tier | Contenu | Bloquant |
|------|------|---------|----------|
| **vital** | 1 | build, bundle_size, build_perf, no_critical_js, backend unit, rust clippy/test, **frontend unit** | Oui |
| **legacy** | 2 | integration (backend), startup_time, memory_budget | Non (warning) |
| **nightly** | 3 | E2E Playwright, contract, Storybook audit | Non |
**Changement majeur** : `frontend/unit.sh` ajouté au plan vital. Exécute `npm run test -- --run` sans `|| true`.
---
## 6. COUVERTURE & TMT
| Plan | Couverture produite | Agrégation | Seuils |
|------|---------------------|-------------|--------|
| **vital** | `vitest run --coverage`, `go test -coverprofile` | Rapports séparés par composant | Évalués en CI ; échec si seuils non atteints |
| **legacy** | Idem | Idem | Indicateur |
| **nightly** | E2E (pas de coverage classique) | Playwright HTML report | Binaire (pass/fail) |
**Agrégation** : pas de rapport global unique. Chaque composant (frontend, backend) a ses seuils. CI échoue si un seuil est violé.
**Aucun** `|| true`. Aucune exception silencieuse.
---
## 7. INTÉGRATION CI
**Principe** : La CI est une **projection fidèle** de l'exécution TMT.
### 7.1 Règle
La CI ne doit **jamais** appeler directement `vitest`, `go test`, `playwright`.
Elle appelle **toujours** `tmt run plan --name /vital` (ou équivalent).
### 7.2 Schéma cible
```yaml
# .github/workflows/ci.yml (simplifié)
jobs:
test:
steps:
- uses: actions/checkout@v4
- name: Install TMT
run: pip install tmt
- name: Run Vital Tests
run: tmt run plan --name /vital
# Plus de go test, npm test, etc. directs
```
### 7.3 Workflows à corriger/supprimer
| Workflow | Action | Raison |
|----------|--------|--------|
| `ci.yml` | Remplacer jobs par `tmt run` | Point d'entrée unique |
| `frontend-ci.yml` | Supprimer | Chemin `apps/web-frontend` inexistant |
| `backend-ci.yml` | Supprimer | Chemin `apps/backend-api` inexistant |
| `playwright.yml` | Intégrer dans TMT nightly ou garder séparé avec `working-directory: apps/web` | E2E nécessite runtime différent |
---
## 8. FEUILLE DE ROUTE
### Phase 1 — Rétablissement de la vérité (12 semaines)
| Priorité | Action | Effort |
|----------|--------|--------|
| **P0** | Supprimer `|| true` des tests frontend (ci.yml) | 5 min |
| **P0** | Corriger `playlist_duplicate_transaction_test.go:80` (compile) | 2 h |
| **P0** | Exclure/corriger tests Go qui paniquent (testutils, RoomService) | 4 h |
| **P1** | Ajouter `working-directory: apps/web` à playwright.yml | 15 min |
| **P1** | Supprimer frontend-ci.yml, backend-ci.yml (ou corriger chemins) | 15 min |
**Objectif** : tests qui échouent = build rouge assumé.
### Phase 2 — Couverture ciblée (13 mois)
| Priorité | Action | Effort |
|----------|--------|--------|
| **P1** | Réparer tests auth middleware (Go) | 8 h |
| **P1** | Ajouter `tmt/tests/frontend/unit.sh` et l'intégrer au plan vital | 2 h |
| **P1** | Faire appeler la CI `tmt run plan --name /vital` | 4 h |
| **P2** | Validation seuils coverage en CI (par domaine) | 8 h |
| **P2** | Remplacer jest.spyOn par vi.spyOn | 2 h |
| **P2** | Tests branches d'erreur sur auth, RBAC, client API | 24 h |
**Objectif** : ajout de tests uniquement sur zones critiques ; suppression de tests toxiques.
### Phase 3 — Stabilisation (24 semaines)
| Priorité | Action | Effort |
|----------|--------|--------|
| **P2** | Temps d'exécution suite unitaire < 2 min (frontend) | Variable |
| **P2** | Flakiness = 0 (audit, correction) | Variable |
| **P3** | Découper client.ts (modules testables) | 40 h |
| **P3** | Unifier auth (Context Store) | 24 h |
**Objectif** : temps maîtrisé ; zéro tolérance au flaky.
---
## 9. LIVRABLE — LISTE PRIORISÉE
### 9.1 Tests à écrire
| Domaine | Fichier / Zone | Type | Priorité |
|---------|----------------|------|----------|
| Auth | `internal/core/auth` | Unit (chemins erreur) | P0 |
| RBAC | `rbac_auth_middleware_test.go` | Corriger mocks | P0 |
| Client API | `client.ts` (après découpage) | Interceptors, retry | P1 |
| Commerce | `marketplaceService`, `cartStore` | Unit | P1 |
| Webhooks | `webhookService`, handlers | Unit + integration | P1 |
| Optimistic | `optimisticUpdates.ts` | Rollback, invalidation | P2 |
### 9.2 Tests à corriger
| Test | Action | Priorité |
|------|--------|----------|
| `auth_middleware_test.go` | Aligner mocks avec ValidateSession | P0 |
| `rbac_auth_middleware_test.go` | Aligner mocks HasRole/HasPermission | P0 |
| `PlaylistErrorBoundary.test.tsx` | jest vi | P1 |
| `auth.integration.test.tsx` | Réduire mocks, scinder | P2 |
### 9.3 Tests à supprimer
| Test | Raison | Priorité |
|------|--------|----------|
| Snapshots sans assertion sémantique | Illusion de couverture | P2 |
| Tests redondants (framework only) | Aucune valeur métier | P2 |
| Tests orphelins (`jest.config.js` si Jest inutilisé) | Nettoyage | P3 |
---
## 10. RÉSUMÉ EXÉCUTIF
| Principe | Décision |
|----------|----------|
| **Couverture** | Différenciée par domaine ; domaines critiques 90% branches |
| **Faux positifs** | Suppression de `\|\| true` ; tests cassés = build rouge |
| **Mocking** | Réduction ; composition testable ; 5 mocks par test |
| **TMT** | Point d'entrée unique ; CI appelle `tmt run` |
| **Phases** | 1. Vérité 2. Couverture ciblée 3. Stabilisation |
**Phrase de clôture** : *Une régression significative ne peut plus passer inaperçue* à condition que les phases 1 et 2 soient exécutées sans compromis.
---
**Fin du document.**