test(charge): mesure l'API sous charge avec k6

Aucun garde-fou de performance n'existait, et le dépôt ne chiffrait aucun temps de réponse.

tests/load, quatre scénarios :
- smoke : une minute sur chaque route de lecture, joué à chaque PR ;
- charge : 50 utilisateurs, 40 sur le tableau de bord au rythme de son rafraîchissement,
  10 qui explorent les sites ;
- stress : débit croissant jusqu'à la rupture, arrêt au-delà de 10 % d'erreurs ;
- limitation-debit : par le proxy, vérifie que nginx répond 429 et jamais 5xx.

Seuils : p95 < 500 ms et p99 < 1 s sur les lectures, moins de 1 % d'échecs.

k6 tourne en service Compose (profil load) sur le réseau du projet : il vise backend:8000 et
mesure l'API plutôt que la limite de 20 req/s par adresse de nginx. Chaque tir écrit un rapport
HTML, une synthèse Markdown et le JSON brut dans tests/load/results.

make load-smoke, load-test, load-stress et load-limits ; le job E2E enchaîne le smoke et le
test de limitation après Playwright.

Closes #47
This commit is contained in:
Johan LEROY
2026-09-23 09:29:20 +02:00
parent a197af91ff
commit 2ed9e1cee4
11 changed files with 460 additions and 2 deletions
+30 -1
View File
@@ -15,7 +15,7 @@ permissions:
jobs:
parcours:
name: Parcours Playwright
name: Parcours Playwright et tirs k6
runs-on: ubuntu-latest
timeout-minutes: 30
env:
@@ -82,6 +82,35 @@ jobs:
E2E_COMPTES: ${{ runner.temp }}/comptes.json
run: npx playwright test
# Direct sur `backend:8000` : ce tir mesure l'API, pas la limitation de nginx.
- name: Tir k6 de fumée sur l'API
env:
K6_RESUME: /results/resume-smoke.md
run: |
K6_EMAIL="$(jq -r .lecteur.email "$RUNNER_TEMP/comptes.json")"
K6_PASSWORD="$(jq -r .lecteur.password "$RUNNER_TEMP/comptes.json")"
echo "::add-mask::$K6_PASSWORD"
export K6_EMAIL K6_PASSWORD
make load-smoke
- name: Vérifie par k6 que le proxy limite le débit
env:
K6_RESUME: /results/resume-limitation.md
run: make load-limits
- name: Publie la synthèse k6
if: ${{ !cancelled() }}
run: cat tests/load/results/resume-*.md >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || true
- name: Publie les rapports k6
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7
with:
name: k6-rapports
path: tests/load/results/
if-no-files-found: ignore
retention-days: 14
- name: Publie le rapport Playwright
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7