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>
9.4 KiB
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.
Чек-лист
- 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/+ JSONreports/results.json. - 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-дрейфу. - 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. - 4. Forgejo workflow
.forgejo/workflows/regression.yml— onworkflow_runпосле Docker API/Web, wait-for-ready → install pnpm + chromium → flows + visual → артефакты + Telegram на падение. Cache на pnpm-store + Playwright-browsers — повторный прогон ~3 мин. - 5. Nightly cron —
~/nightly-verify.sh+ cron0 4 * * *: health-check → если падает, redeploy-stage → smoke flows (@smoketag) → в воскресенье ещё полный flows + visual. Лог~/.fm-watchdog/nightly-YYYYMMDD.log, ротация >14 дней. Telegram-уведомление если упало (читает токен из~/.fm-watchdog/telegram-token). - 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»).
- 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:dotnet test --collect:"XPlat Code Coverage",bash scripts/generate-badges.sh,- diff → commit
chore(badges): update coverage [skip ci]→ push.
Nightly cron
- Скрипт
~/nightly-verify.sh(217 строк bash). - Crontab:
0 4 * * * /home/nns/nightly-verify.sh. - Последовательность:
curl /health/ready— если не Healthy →~/deploy-stage.sh→ повторная проверка → если опять упала → Telegram + exit.pnpm install(если node_modules нет) +playwright test flows/ --grep @smoke.- Если воскресенье — полный прогон
flows/ visual/. - 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 —
rowsOfhelper. - 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 или более широкую маску.