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

9.4 KiB
Raw Permalink Blame History

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 suitetests/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.
  • 2. Visual regressiontests/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 factoriestests/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 — on workflow_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 + cron 0 4 * * *: health-check → если падает, redeploy-stage → smoke flows (@smoke tag) → в воскресенье ещё полный 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»).

Замеры

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.ymlon 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 Webregression.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 или более широкую маску.