- ADR 0014 : un pipeline CI unique, « CI ok » seul check à exiger, déploiement du commit testé. - ADR 0015 : e2e et charge contre la stack Compose déployée, hypothèses et seuils de k6. - ADR 0016 : supervision en profil Compose, active en prod, rôle en lecture seule. - Nouvelle vue 60-observabilite.md ; 00-vue-ensemble, 10-infra, 20-backend et 50-cicd mis à jour (monitoring passé à Fait, nouveau graphe de CI, gates, ports). - README racine et guide de tests du frontend : où sont l'e2e, la charge et la supervision.
4.1 KiB
0015 - Les tests de bout en bout et de charge visent la stack Compose déployée
- Statut : accepté
- Date : 2026-09-23
Contexte
Les issues #46 (Playwright) et #47 (k6) demandent des preuves de robustesse pour EC03 et EC04. Rien ne vérifiait un parcours utilisateur complet : les tests du frontend simulent l'API, ceux du backend n'ouvrent pas de navigateur. Rien ne mesurait non plus l'API sous charge, et le dépôt ne chiffre aucun temps de réponse ni aucun volume d'utilisateurs.
Trois contraintes du système pèsent sur la manière de tester :
- La session tient dans un cookie de refresh HttpOnly qui tourne à chaque usage. Rejouer un cookie déjà servi révoque toute la famille de session (ADR 0002).
- Le cookie n'est
__Secure-etSecureque horslocal, derrière le proxy TLS. Tester contreng servene dit rien de ce que voit un navigateur en prod (ADR 0007). - nginx limite chaque adresse IP à 20 req/s sur l'API, avec une rafale de 40, et à 30 connexions par minute, avec une rafale de 20 (ADR 0007). Tout le trafic d'un tir parti d'une seule machine partage la même adresse.
Décision
Playwright joue contre la stack de prod (docker-compose.yml et
docker-compose.prod.yml), sur https://localhost avec un certificat auto-signé.
- En CI, le workflow
e2e.ymldémarredb,mailpit,backend,frontendetproxy, sèmedb/seeds/demo.sqlet crée les comptes parscripts/comptes-test.sh. - Sur le poste, la même suite vise
make dev(http://localhost:4200). - Écriture des tests, imposée par la rotation du refresh et par la zone
auth:- un seul worker ;
- une session par fichier, sans
storageStatepartagé ; - chaque parcours qui consomme un compte le crée lui-même.
k6 tourne en service Compose (profil load) sur le réseau du projet et vise backend:8000,
pour mesurer l'API et non la limite de nginx. Un seul scénario, limitation-debit.js, passe par
https://proxy, pour vérifier que la limite tient : des 429, jamais de 5xx.
Hypothèses et seuils, faute d'exigence chiffrée :
| Hypothèse ou seuil | Valeur |
|---|---|
| Utilisateurs simultanés | 50 : 40 sur le tableau de bord, qui interroge /stats/summary toutes les 10 s et /alerts toutes les 60 s ; 10 qui explorent les sites |
| Lectures, p95 | < 500 ms |
| Lectures, p99 | < 1 s |
| Échecs HTTP | < 1 % |
| Vérifications réussies | > 99 % |
En CI de PR : Playwright, le tir smoke (une minute) et limitation-debit. La charge
nominale et le stress se lancent à la main (make load-test, make load-stress), en recette,
parce que rec et prod partagent la VM (ADR 0009).
Alternatives écartées
| Écartée | Raison |
|---|---|
Playwright contre ng serve en CI |
Pas de TLS, pas de cookie __Secure-, pas de CSP ni de limitation : le parcours testé ne serait pas celui des utilisateurs. |
storageState partagé entre fichiers |
Chaque fichier rejouerait le même cookie de refresh ; le second usage révoque la famille, et la suite échoue de façon intermittente selon l'ordre. |
| k6 depuis le runner, à travers le proxy | Au-delà de 20 req/s, on mesure nginx. Relever la limite pour le tir, ce serait tester une configuration qui n'est pas celle de la prod. |
| Tir de charge complet à chaque PR | Huit minutes de plus par PR, sur un runner partagé dont les performances varient d'un run à l'autre : un seuil franchi n'y voudrait rien dire. |
Un workflow k6 en workflow_dispatch contre la recette |
La recette partage la VM avec la prod ; un tir déclenché d'un clic ralentirait la prod sans que personne soit prévenu. La cible Makefile, lancée sur la VM, garde un humain dans la boucle. |
Conséquences
- La CI construit enfin les images backend et frontend avant le déploiement, par le job E2E.
db/seeds/demo.sqletscripts/comptes-test.shdeviennent le jeu commun de la CI, repris par le DAST. Les deux sont réservés aux bases jetables.- Les seuils de k6 sont des hypothèses de l'équipe : à réviser dès qu'un besoin chiffré existe.
- L'API expose des seaux de latence fins autour de 500 ms, pour que Grafana lise le même seuil que k6 (ADR 0016).