- preflight занятого логина и неактивной целевой группы - applied=false с номером строки, без частичных студентов - LDD-IMPORT-003; baseline 58 claims / 368 тестов
118 lines
6.9 KiB
Markdown
118 lines
6.9 KiB
Markdown
# LDD: доказательное тестирование
|
||
|
||
Этот каталог — реестр утверждений о системе и свидетельств того, что они
|
||
выполняются. LDD здесь означает не «тесты вместо требований», а
|
||
**риск-ориентированную проверку**: требование → проверяемое утверждение →
|
||
независимый оракул → воспроизводимое свидетельство → допуск.
|
||
|
||
## Уровни
|
||
|
||
- **P0** — утверждение о безопасности, сохранности данных, доступах или
|
||
ключевом доменном правиле. P0 без зелёного свидетельства валит
|
||
`./gradlew evidenceCheck`.
|
||
- **P1** — важное поведение/UX/контракт. Пробел показывается в отчёте, но не
|
||
блокирует сборку.
|
||
- **runtime** — проверка на реально поднятом стеке. Быстрый smoke
|
||
(`scripts/ldd-smoke.sh`) выполняется в CI на каждом push/MR; полный
|
||
runtime/scale — в workflow `release` и обязателен перед релизом.
|
||
|
||
## Реестр
|
||
|
||
`claims.json` содержит:
|
||
|
||
- `id` — стабильный идентификатор (`LDD-ACCESS-001`);
|
||
- `title` — короткая формулировка;
|
||
- `criticality` — `P0`/`P1`;
|
||
- `status` — `active` или `gap`;
|
||
- `requirement` — ссылка на ТЗ/отчёт;
|
||
- `claim` — проверяемое утверждение (что именно истинно);
|
||
- `oracle` — как это проверяется;
|
||
- `evidence` — список `fully.qualified.Class#test name()` из JUnit XML;
|
||
- `runtime` — идентификаторы проверок из `build/evidence/runtime.json`;
|
||
- `limitations` — что утверждение **не** покрывает.
|
||
|
||
## Запуск
|
||
|
||
```bash
|
||
# 1. Все тесты и линтеры
|
||
./gradlew test ktlintCheck detekt
|
||
|
||
# 2. Гейт свидетельств (P0 без evidence = fail)
|
||
./gradlew evidenceCheck
|
||
|
||
# 3. Быстрый smoke полного стека (то же, что workflow smoke)
|
||
./scripts/ldd-smoke.sh
|
||
|
||
# 4. Полный runtime-smoke + scale load на одноразовой БД
|
||
./scripts/ldd-runtime.sh
|
||
|
||
# 5. Проверка upgrade с master-схемы
|
||
./scripts/ldd-migration-upgrade.sh
|
||
|
||
# 6. Mutation testing критичных P0-компонентов
|
||
./scripts/ldd-mutation.sh
|
||
|
||
# 7. Браузерный E2E (Playwright: Chromium/Firefox/WebKit)
|
||
./scripts/ldd-browser.sh
|
||
|
||
# 8. Полный release gate
|
||
./scripts/ldd-release.sh
|
||
```
|
||
|
||
Для E2E один раз установите зависимости и браузеры: `cd e2e && npm install && npx playwright install chromium firefox webkit`.
|
||
Mutation harness использует JUnit 4: JUnit5-плагин PIT несовместим с JUnit
|
||
Platform 6 из Spring Boot 4.
|
||
|
||
Отчёт: `build/reports/evidence/index.md`.
|
||
|
||
## Правила
|
||
|
||
1. Новое P0-требование без свидетельства не мержится.
|
||
2. Свидетельство должно быть воспроизводимым в CI, а не «проверил руками».
|
||
3. Тест должен падать при поломке соответствующей логики. Для критичных
|
||
пакетов это измеряется mutation testing: сейчас `CourseAccessService` —
|
||
75% test strength, `PromotionPlanner` — 69%.
|
||
4. Один тест может подтверждать несколько claims, но claim не должен
|
||
опираться на тест, который проверяет только реализацию.
|
||
5. `limitations` обязателен: LDD не должен создавать иллюзию полного
|
||
доказательства.
|
||
6. При переименовании теста обновляется `claims.json`; устаревшая ссылка —
|
||
это gap, а не «забыли».
|
||
7. Runtime-свидетельства обязательны перед релизом; CI на каждом push/MR
|
||
выполняет unit/integration-слой и быстрый smoke, полный release gate —
|
||
для тегов (вручную для веток).
|
||
|
||
## Текущий baseline
|
||
|
||
LDD-циклы выполнены 2026-10-27/28; последний — после закрытия продуктовых
|
||
рисков:
|
||
|
||
- **368 автоматических тестов**, 0 failures/errors;
|
||
- **58 claims**: 27 P0 + 31 P1, **58/58 proven, P0 gaps = 0**. P0 — доступы,
|
||
повышение, жизненный цикл, профиль/скачивание, материалы/активы
|
||
(включая secure-by-default legacy-файлы), миграции V11–V13, аудит,
|
||
refresh-токены и их отзыв; P1 — группы, авторство, UI, контракты, импорт,
|
||
копирование лаб, keyset-пагинация, пакетные детали лабораторных,
|
||
абсолютный потолок сессии, runtime, mutation и browser E2E;
|
||
- mutation testing: `CourseAccessService` 75% test strength,
|
||
`PromotionPlanner` 69%;
|
||
- Playwright: 6 сценариев (admin, teacher, student/anonymous, сдача+mobile,
|
||
cursor-аудит, инвентаризация активов) × Chromium/Firefox/WebKit = **18/18**,
|
||
все зелёные;
|
||
- масштабный load: 100 групп / 1000 студентов, 125 параллельных чтений,
|
||
0 ошибок, p95 < 1 с (порог p95 < 2 с);
|
||
- CI: Gitea + Woodpecker, workflow `smoke` (`ldd-smoke.sh`) на каждом push/MR;
|
||
полный `release` (`ldd-release.sh`) обязателен для тегов и ручной для веток.
|
||
Установка — `deploy/WOODPECKER.md`.
|
||
|
||
В ходе E2E найден и исправлен реальный дефект: Jackson 3 не применял
|
||
Kotlin-модуль, поэтому DTO с default-значениями требовали все поля JSON
|
||
(например, создание студента без `firstName`/`basis` давало 400).
|
||
|
||
Остаточные ограничения: ручная инвентаризация legacy-активов на production,
|
||
сдачи по выбранной лабораторной в ведомости, непроверенный первый CI-прогон на
|
||
реальных runner'ах и отсутствие визуальной регрессии. Legacy-активы, срок
|
||
access-токена, пагинация, N+1 деталей лабораторных, абсолютный лимит сессии и
|
||
«ведущие нули» больше не являются открытыми рисками.
|
||
Результаты — в `baseline-2026-10-27.md`.
|