food-market/docs/sprint16-progress.md
nns 1989db32bb test(s16): regression suite 35 flows + visual 60 snapshots + nightly + CI badges
Sprint 16 — постоянный regression-контур: flows + visual + nightly +
CI workflow + README badges.

Ключевые цифры:
- 35 flow-тестов: 35/35 ✓ за ~30 секунд (workers=2 локально).
- 60 visual snapshot'ов (15 страниц × 2 темы × 2 viewport'a):
  60/60 ✓ за ~4 минуты с retries=1.
- Полный регресс прогон: ~5 минут (цель была < 15).

Что сделано:
1. tests/regression/ — Playwright + factories + 8 spec-файлов.
   OrgFactory builder создаёт org через API за O(N) HTTP вызовов
   (signup → token → refs → products → counterparties → posted supplies).
   Каждый flow независим, использует свой fresh-org.
2. tests/regression/visual/ — 15 страниц × 2 темы × 2 viewport'a.
   Маски на динамический контент (артикулы с Date.now, KPI'ы,
   delta-стрелки) чтобы 0.2% threshold не флакал. snapshotPathTemplate
   c {projectName} — desktop+mobile не затирают друг друга.
3. tests/regression/factories/OrgFactory.ts — builder с .withProducts
   .withCounterparties .withSupplies. Retry signup'a на 429.
4. .forgejo/workflows/regression.yml — on workflow_run после
   Docker API/Web; cache на pnpm-store + Playwright-browsers;
   артефакты при failure; Telegram-уведомление в обоих случаях.
5. ~/nightly-verify.sh + cron `0 4 * * *`: health → redeploy если
   нужно → smoke flows; в воскресенье полный flows+visual. Логи с
   ротацией 14 дней. Telegram на провал (~/.fm-watchdog/telegram-*).
6. scripts/generate-badges.sh — coverage из cobertura.xml в SVG через
   shields.io (offline fallback). 4 CI-status badge + coverage badge в
   README; CI step «Update coverage badge» авто-коммитит обновлённый
   SVG на push в main.

Локальное число flake'ов: 1/60 visual на retry=1 (product-new light) —
случайная гонка маски, retry'ит и проходит.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 16:14:11 +05:00

168 lines
9.4 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.

# Sprint 16 — E2E regression suite + visual regression + nightly verify
Цель: построить «постоянный» regression-контур, чтобы регресс ловился
сам — не «вспомнили посмотреть». 35 user-flow specs + 60 visual
snapshot'ов + автоматический nightly + CI на каждый push в main.
Старт: 2026-06-07 (после Sprint 15). Исполнитель: Claude Opus 4.7.
## Принципы
- Каждый flow — независимый, использует фабрику для подготовки данных
через API (не через UI-клики).
- Visual baseline — fresh stage post-deploy. Diff threshold 0.2% +
маски на динамический контент (timestamps в артикулах, KPI).
- Полный прогон < 15 минут (Playwright workers + retry=1 на CI).
- НЕ трогать: `global.json`, prod admin.food-market.kz, POS WPF.
## Чек-лист
- [x] **1. Regression suite** `tests/regression/flows/` **35 ключевых
flow-тестов** в 8 spec-файлах (auth, catalog, documents post/unpost,
reports, multi-tenant isolation, i18n+permissions+2FA+audit,
realtime+misc). Прогон параллелен (workers=2 локально, 4 на CI).
Отчёт `reports/playwright-html/` + JSON `reports/results.json`.
- [x] **2. Visual regression** `tests/regression/visual/`
**60 snapshot'ов** (15 страниц × 2 темы × 2 viewport'a:
desktop 1280×800 + mobile Pixel 5 375×667). Threshold 0.002 (0.2%) +
маски на артикулы/KPI/delta'ы для устойчивости к timestamp-дрейфу.
- [x] **3. Test data factories** `tests/regression/factories/`
`OrgFactory.for(slug).withProducts(N).withCounterparties(M).withSupplies(K).build()`
собирает org через API за O(N) HTTP-вызовов (signup token refs
products counterparties posted supplies). Используется в каждом
flow-тесте вместо signup-form.
- [x] **4. Forgejo workflow `.forgejo/workflows/regression.yml`**
on `workflow_run` после Docker API/Web, wait-for-ready install
pnpm + chromium flows + visual артефакты + Telegram на падение.
Cache на pnpm-store + Playwright-browsers повторный прогон ~3 мин.
- [x] **5. Nightly cron** `~/nightly-verify.sh` + cron `0 4 * * *`:
health-check если падает, redeploy-stage smoke flows
(`@smoke` tag) в воскресенье ещё полный flows + visual.
Лог `~/.fm-watchdog/nightly-YYYYMMDD.log`, ротация >14 дней.
Telegram-уведомление если упало (читает токен из
`~/.fm-watchdog/telegram-token`).
- [x] **6. README badges** — добавлены 4 CI-status badge (CI, Docker API,
Stage verify, Regression — берутся с Forgejo `actions/workflows/*.svg`)
+ coverage badge (`badges/coverage.svg`, генерируется
`scripts/generate-badges.sh` из cobertura.xml, авто-коммит из CI step
«Update coverage badge»).
## Замеры
### Regression suite stats
| Файл | Tests | Время (workers=2) |
|---|---|---|
| `flows/01-factory-smoke.spec.ts` | 1 | 5s |
| `flows/02-auth.spec.ts` | 4 (login/signup/refresh/wrong-pw) | 4s |
| `flows/03-catalog.spec.ts` | 5 (CRUD product/counterparty/store/price-type) | 6s |
| `flows/04-documents.spec.ts` | 8 (supply/enter/retail-sale/loss/transfer/demand/supplier-return post+unpost) | 12s |
| `flows/05-reports.spec.ts` | 4 (sales/stock/profit/abc с проверкой чисел) | 6s |
| `flows/06-multi-tenant.spec.ts` | 3 (list-isolation, get-by-id-isolation, sales-isolation) | 4s |
| `flows/07-i18n-permissions.spec.ts` | 5 (locale switch, 2FA enroll, audit log, anon→401) | 5s |
| `flows/08-realtime-misc.spec.ts` | 5 (dashboard render, search, /health/ready) | 6s |
| **Total** | **35** | **~30 секунд** ✓ |
| Visual project | Snapshot count | Время |
|---|---|---|
| `desktop-chromium` 1280×800 | 30 (15 страниц × 2 темы) | 2m 10s |
| `mobile-chromium` 375×667 (Pixel 5) | 30 | 2m 5s |
| **Total** | **60** | **~4 минуты** |
**Общий прогон**: ~30 сек (flows) + ~4 мин (visual) = **< 5 минут** end-to-end
существенно ниже 15-минутного целевого порога.
### Coverage badge
- `scripts/generate-badges.sh` берёт cobertura.xml, считает покрытие
по Application + Domain (combined), генерирует SVG через shields.io
(offline fallback inline).
- Текущее значение: **80%** (от Sprint 15 baseline).
- Цвет шкалы: <50% red, 50-69% yellow, 70-84% green, 85% brightgreen.
- CI step «Update coverage badge» (`.forgejo/workflows/ci.yml`) на
каждый push в main:
1. `dotnet test --collect:"XPlat Code Coverage"`,
2. `bash scripts/generate-badges.sh`,
3. diff commit `chore(badges): update coverage [skip ci]` push.
### Nightly cron
- Скрипт `~/nightly-verify.sh` (217 строк bash).
- Crontab: `0 4 * * * /home/nns/nightly-verify.sh`.
- Последовательность:
1. `curl /health/ready` если не Healthy `~/deploy-stage.sh` повторная проверка если опять упала Telegram + exit.
2. `pnpm install` (если node_modules нет) + `playwright test flows/ --grep @smoke`.
3. Если воскресенье полный прогон `flows/ visual/`.
4. Telegram-уведомление при провале (`~/.fm-watchdog/telegram-{token,chat}`).
- Логи: `~/.fm-watchdog/nightly-YYYYMMDD.log`, `find -mtime +14 -delete`
чистит каждый запуск.
## Журнал
### 2026-06-07 старт
Sprint 15 закрыт (7/7 ✓). Поехали по regression-чек-листу.
### 2026-06-07 п.3 (factory) — фундамент
`tests/regression/factories/OrgFactory.ts` + `api-client.ts` + `types.ts`.
Builder-pattern: `OrgFactory.for(slug).withProducts(N)…build()`.
Реквест-клиент на `fetch` (Node 20+), retry на 429 со сдвинутым backoff
(под Sprint 13 IP-лимит signup'a).
### 2026-06-07 п.1 (35 flows)
8 spec-файлов с тегами `@smoke` на ключевых flows для быстрого прогона.
API-driven где возможно (быстрее UI-кликов), Playwright UI только там
где нужно (form-login, dashboard render, локаль switch).
Несколько мелких фиксов по ходу:
- Profit/ABC report возвращают непосредственно List, не PagedResult `rowsOf` helper.
- Multi-tenant isolation проверять по `id`, не `name` (одинаковые
product-names в разных org'ах норма).
- Login редиректит на «/» (OnboardingPage) на свежей org, не /dashboard.
- Loss-endpoint enum'у reason требует int, не строку.
### 2026-06-07 п.2 (visual 60)
2 spec'a (auth-pages + authenticated-pages). Baseline на свежий
deploy. Маски на динамический контент:
- `table td:nth-child(2)` (артикул с Date.now()),
- `[data-kpi]` (зависит от текущей даты),
- `[data-delta]` (стрелка от prev period).
snapshotPathTemplate включает `{projectName}` чтобы desktop+mobile
snapshot'ы не затирали друг друга.
### 2026-06-07 п.4 (forgejo workflow)
`.forgejo/workflows/regression.yml` `on workflow_run` после
Docker API/Web. Cache на pnpm-store + Playwright-browsers. Артефакты
upload при failure, Telegram-уведомление в обоих случаях.
### 2026-06-07 п.5 (nightly cron)
`~/nightly-verify.sh` + crontab entry. Health redeploy smoke
weekly full + Telegram. Логи с ротацией.
### 2026-06-07 п.6 (badges)
`scripts/generate-badges.sh` coverage из cobertura.xml SVG через
shields.io с offline-fallback. 4 CI-status badge + coverage badge
добавлены в README. CI-step авто-обновляет coverage badge на push в main.
## Итог
Все 6 пунктов ✓. Локальные числа:
- **35 flow-тестов**: 35/35 при workers=2 (~30 сек).
- **60 visual snapshot'ов**: 60/60 при CI=1 (retries=1) (~4 мин).
- **Полный прогон**: ~5 минут **3× ниже** 15-минутного целевого порога.
Контур регрессии работает:
- На каждый push в main: Forgejo `Docker API`/`Docker Web` `regression.yml`
35 flows + 60 visual + Telegram.
- Каждую ночь: nightly cron health smoke (или полный в воскресенье)
+ Telegram при провале.
- Coverage и CI-status badges в README обновляются автоматически.
Следующее расширение (не в этом sprint'е):
- Перенести visual baseline'ы в LFS если они станут большими (сейчас 60
PNG ~10 МБ, в репе ок).
- Добавить performance regression (k6 в CI nightly), сейчас k6 запускается
только вручную.
- Заглушить flake в `product-new light` через определённый wait или
более широкую маску.