docs: LDD baseline с mutation и browser E2E

This commit is contained in:
2026-10-28 00:02:06 +03:00
parent b7129b92e0
commit 238fd91f69
4 changed files with 120 additions and 49 deletions

View File

@@ -294,9 +294,10 @@ upgrade-тест миграций, видимость активов и deploy-r
## 7. LDD baseline
После этапа 6 текущая функциональность проверена через LDD-контур:
реестр `docs/evidence/claims.json` (31 claim, 19 P0 / 12 P1), gate
`./gradlew evidenceCheck`, upgrade-скрипт и runtime-smoke полного стека.
Результат: **31/31 claims proven, P0 gaps = 0**, 267 тестов, upgrade с
master-схемы и E2E-поток «админ → группа → курс → преподаватель → лаба»
проходят. Подробности и остаточные ограничения —
реестр `docs/evidence/claims.json` (34 claim, 19 P0 / 15 P1), gate
`./gradlew evidenceCheck`, upgrade-скрипт, runtime-smoke, mutation testing
и браузерный Playwright E2E. Результат: **34/34 claims proven, P0 gaps = 0**,
273 теста; mutation strength `CourseAccessService` 75%,
`PromotionPlanner` 69%; browser E2E 3/3. E2E нашёл и закрыл реальный дефект
Jackson 3/Kotlin defaults. Подробности и остаточные ограничения —
[`docs/evidence/baseline-2026-10-27.md`](evidence/baseline-2026-10-27.md).

View File

@@ -44,16 +44,27 @@
# 4. Проверка upgrade с master-схемы
./scripts/ldd-migration-upgrade.sh
# 5. Mutation testing критичных P0-компонентов
./scripts/ldd-mutation.sh
# 6. Браузерный E2E (Playwright + Chromium)
./scripts/ldd-browser.sh
```
Для E2E один раз установите зависимости: `cd e2e && npm install`.
Mutation harness использует JUnit 4: JUnit5-плагин PIT несовместим с JUnit
Platform 6 из Spring Boot 4.
Отчёт: `build/reports/evidence/index.md`.
## Правила
1. Новое P0-требование без свидетельства не мержится.
2. Свидетельство должно быть воспроизводимым в CI, а не «проверил руками».
3. Тест должен падать при поломке соответствующей логики; для критичных
пакетов позже добавим mutation testing.
3. Тест должен падать при поломке соответствующей логики. Для критичных
пакетов это измеряется mutation testing: сейчас `CourseAccessService` —
75% test strength, `PromotionPlanner` — 69%.
4. Один тест может подтверждать несколько claims, но claim не должен
опираться на тест, который проверяет только реализацию.
5. `limitations` обязателен: LDD не должен создавать иллюзию полного
@@ -65,12 +76,21 @@
## Текущий baseline
Первый прогон LDD выполнен 2026-10-27:
Первый LDD-цикл выполнен 2026-10-27/28:
- 267 автоматических тестов, 0 failures/errors;
- 33 claims: P0 — доступы, повышение, жизненный цикл, профиль/скачивание,
материалы/активы, миграция V13, аудит; P1 — группы, авторство, UI,
контракты, импорт, копирование лаб, runtime.
- Runtime-smoke и master-upgrade вынесены в отдельные скрипты.
- **273 автоматических теста**, 0 failures/errors;
- **34 claims**: 19 P0 + 15 P1. P0 — доступы, повышение, жизненный цикл,
профиль/скачивание, материалы/активы, миграция V13, аудит; P1 — группы,
авторство, UI, контракты, импорт, копирование лаб, runtime, mutation и
browser E2E;
- mutation testing: `CourseAccessService` 75% test strength,
`PromotionPlanner` 69%;
- Playwright: 3 сценария (admin, teacher, student/anonymous), все зелёные;
- runtime-smoke, master-upgrade, mutation и browser E2E вынесены в отдельные
скрипты.
Результаты и найденные пробелы — в `baseline-2026-10-27.md`.
В ходе E2E найден и исправлен реальный дефект: Jackson 3 не применял
Kotlin-модуль, поэтому DTO с default-значениями требовали все поля JSON
(например, создание студента без `firstName`/`basis` давало 400).
Результаты и остаточные ограничения — в `baseline-2026-10-27.md`.

View File

@@ -1,18 +1,19 @@
# LDD baseline: 2026-10-27
# LDD baseline: 2026-10-27/28
Первый прогон доказательной проверки текущей функциональности LMS.
Код приложения в этом прогоне не менялся; добавлены реестр claims, gate
`evidenceCheck`, runtime- и migration-скрипты.
Первый и второй LDD-циклы проверки текущей функциональности LMS.
Добавлены реестр claims, gate `evidenceCheck`, runtime/migration/mutation
скрипты и браузерный E2E на Playwright. В ходе проверки найден и исправлен
реальный дефект Jackson 3.
## 1. Что проверялось
Реестр: `docs/evidence/claims.json`, 31 утверждение.
Реестр: `docs/evidence/claims.json`, **34 утверждения**.
| Критичность | Claims | Proven | Gaps |
|---|---:|---:|---:|
| P0 | 19 | 19 | 0 |
| P1 | 12 | 12 | 0 |
| **Итого** | **31** | **31** | **0** |
| P1 | 15 | 15 | 0 |
| **Итого** | **34** | **34** | **0** |
Домены:
@@ -24,8 +25,9 @@
- материалы и активы;
- миграция V13 и полный upgrade с master-схемы;
- аудит: токен, admin-only, сохранность после удаления, representative-хуки;
- группы курса, авторство материалов, ведомость, UI/контракты, импорт, копирование лаб;
- runtime-smoke полного стека.
- группы курса, авторство материалов, ведомость, UI/контракты, импорт,
копирование лабораторных;
- runtime-smoke, mutation testing, браузерный E2E.
## 2. Команды и результаты
@@ -35,7 +37,7 @@
./gradlew test --rerun-tasks
```
Результат: **267 тестов, 0 failures, 0 errors, 0 skipped**.
Результат: **273 теста, 0 failures, 0 errors, 0 skipped**.
`ktlintCheck` и `detekt` — зелёные.
### 2.2. LDD gate
@@ -44,7 +46,7 @@
./gradlew evidenceCheck
```
Результат: **31/31 claims proven, P0 gaps = 0**.
Результат: **34/34 claims proven, P0 gaps = 0**.
Отчёт: `build/reports/evidence/index.md`.
Gate устроен так:
@@ -94,49 +96,94 @@ identity `V4–V10`, academic `V6–V12`, progress `V13`.
- чужой преподаватель получает `403` на курс, лабу и аудит;
- админ видит audit-события `COURSE_CREATE`, `TEACHER_CREATE`,
`COURSE_TEACHER_ASSIGN`, `COURSE_GROUP_ATTACH`, `LAB_CREATE`;
- web `/login` отдаёт `200`, публичное дерево материалов доступно, курсовая
- web `/login` отдаёт `200`, публичное дерево материалов доступно, курсовые
материалы анонимно — `401`.
Результат: **PASS**, evidence: `build/evidence/runtime.json`.
Стек и одноразовая БД после прогона остановлены/удалены.
### 2.5. Mutation testing
```bash
./scripts/ldd-mutation.sh
```
PIT запускается через CLI с JUnit 4 harness: JUnit5-плагин PIT несовместим
с JUnit Platform 6 из Spring Boot 4.
| Компонент | Мутаций | Убито | Test strength | Порог |
|---|---:|---:|---:|---:|
| `CourseAccessService` | 56 | 42 | **75%** | 70% |
| `PromotionPlanner` | 162 | 109 | **69%** | 60% |
Результат: **PASS**, evidence: `build/evidence/mutation.json`.
Остаток — эквивалентные мутации, Kotlin-интринсики и ветки, не входящие в
текущий P0-контур.
### 2.6. Браузерный E2E
```bash
./scripts/ldd-browser.sh
```
Playwright/Chromium на полном стеке, одноразовая БД:
- admin: вход, `/admin/courses` с курсом, `/admin/audit` с событием;
- teacher: вход, курс, ведомость (группа/студент, без админских кнопок),
профиль студента, создание главы курса;
- anonymous: `/admin/audit` → `/login`;
- student: вход, `/admin/audit` → `/student`, `/learn/course/{no}`.
Результат: **3/3 passed**, evidence: `build/evidence/browser.json`.
### 2.7. Найденный дефект
Первый browser E2E упал на создании студента: API вернул `400`, потому что
Jackson 3 не применял Kotlin-модуль, и DTO с default-значениями требовали все
поля JSON. Исправлено: `jackson-module-kotlin` для Jackson 3 +
`JsonMapperBuilderCustomizer` в identity/academic/progress/web. Добавлен
регрессионный тест `TeacherIntegrationTest.student creation accepts omitted
optional json fields`.
## 3. Что это доказывает
- Критичные P0-инварианты доступа, повышения, жизненного цикла, профиля,
материалов, миграции и аудита имеют зелёные автоматические свидетельства.
- Приложение собирается, мигрируется с master-схемы и поднимается полным
- Приложение собирается, мигрирует с master-схемы и поднимается полным
стеком на чистой БД.
- Ключевой доменный поток «админ → группа → курс → преподаватель → лаба»
проходит через реальные HTTP/gateway/БД, а не только через mock.
проходит через реальные HTTP/gateway/БД и браузер.
- Чужой преподаватель не получает доступ к курсу/лабе/аудиту на реальном стеке.
- Аудит пишется и читается; upgrade не теряет синтетические данные.
- Мутационная прочность критичных компонентов измерена, а не заявлена.
- Реальный дефект DTO/Jackson найден именно E2E-контуром и закрыт тестом.
## 4. Чего это не доказывает
1. **Нет браузерного E2E.** Thymeleaf-тесты проверяют HTML, но не реальные
клики/JS/CSRF/редиректы в браузере.
2. **Нет нагрузочных и конкурентных испытаний.** Advisory locks и гонки
1. **Нет нагрузочных и конкурентных испытаний.** Advisory locks и гонки
проверены кодом и unit/integration-тестами, но не под нагрузкой.
3. **Нет mutation testing.** Сила тестов измерена косвенно; следующий шаг —
PIT на `CourseAccessService`, `PromotionService`, `StudentProfileService`.
4. **Нет property-based/model-based проверки повышения.** Один сценарный тест
не покрывает все комбинации курсов, степеней и академ-переходов.
2. **Mutation testing не 100%.** Остаются эквивалентные мутанты и
Kotlin/Spring-специфичные мутации; PIT harness — JUnit 4, а не JUnit 5.
3. **Property-based тесты покрывают не все ветки.** Есть генераторы для
матрицы доступа и планировщика повышения, но не для транзакционного
apply/rollback и конкурентных сценариев.
4. **Браузерный E2E — один Chromium и один сценарий на роль.** Нет
визуальной регрессии, мобильных размеров, Safari/Firefox.
5. **Legacy-активы без `article_assets` остаются публичными.**
6. **JWT живёт до 30 дней.** Web перепроверяет статус, прямой API — нет.
7. **Ведущие нули номера группы нормализуются** (`01` → `1`).
8. **Нет пагинации/keyset** для части списков и N+1 в отдельных экранах.
9. **Runtime-smoke не входит в unit-CI**; он запускается отдельным скриптом
перед релизом.
9. **Runtime/mutation/browser E2E не входят в unit-CI**; это release-скрипты.
## 5. Вывод
Текущая функциональность прошла первый LDD-контур: **P0 gaps = 0**,
полный стек и upgrade работают. Это достаточное основание продолжать
доработки, но не «формальное доказательство всей системы». Следующий цикл
LDD должен добавить:
Текущая функциональность прошла LDD-контур: **34/34 claims proven, P0 gaps = 0**,
273 теста, upgrade, mutation baseline и браузерный E2E зелёные. Это
достаточное основание продолжать доработки, но не «формальное доказательство
всей системы».
1. mutation testing для критичных пакетов;
2. property-based тесты повышения и матрицы доступа;
3. браузерный E2E (Playwright) для ведомости, профиля и материалов;
4. нагрузочный smoke на чтение ведомости/профиля;
5. автоматический runtime-smoke в release-пайплайне.
Следующий цикл LDD:
1. нагрузочный smoke на чтение ведомости/профиля и конкурентный apply/rollback;
2. property-based/model-based тесты транзакционного повышения;
3. расширение browser E2E (студенческая сдача, публикация оценки, мобильный вид);
4. автоматический release-пайплайн с runtime/mutation/browser evidence.