docs: LDD baseline с mutation и browser E2E
This commit is contained in:
@@ -56,6 +56,8 @@ progress `:8083`, web `:8090`. Интерфейс: `http://localhost:8090`.
|
|||||||
./gradlew ktlintFormat # автоформат Kotlin
|
./gradlew ktlintFormat # автоформат Kotlin
|
||||||
./scripts/ldd-runtime.sh # runtime-smoke полного стека на одноразовой БД
|
./scripts/ldd-runtime.sh # runtime-smoke полного стека на одноразовой БД
|
||||||
./scripts/ldd-migration-upgrade.sh # upgrade с master-схемы
|
./scripts/ldd-migration-upgrade.sh # upgrade с master-схемы
|
||||||
|
./scripts/ldd-mutation.sh # PIT: mutation strength критичных P0-компонентов
|
||||||
|
./scripts/ldd-browser.sh # Playwright E2E (нужен cd e2e && npm install)
|
||||||
```
|
```
|
||||||
|
|
||||||
- `ktlint` отвечает за формат, `detekt` — за качество (сложность, вложенность, ошибки).
|
- `ktlint` отвечает за формат, `detekt` — за качество (сложность, вложенность, ошибки).
|
||||||
@@ -65,8 +67,9 @@ progress `:8083`, web `:8090`. Интерфейс: `http://localhost:8090`.
|
|||||||
не работает на JDK 25.
|
не работает на JDK 25.
|
||||||
- Тестовая инфраструктура — `libs:test-support` (JUnit 5, MockK, Testcontainers `postgres:18`).
|
- Тестовая инфраструктура — `libs:test-support` (JUnit 5, MockK, Testcontainers `postgres:18`).
|
||||||
- **LDD** — реестр проверяемых утверждений `docs/evidence/claims.json`;
|
- **LDD** — реестр проверяемых утверждений `docs/evidence/claims.json`;
|
||||||
P0 без зелёного теста валит `./gradlew evidenceCheck`. Runtime- и
|
P0 без зелёного теста валит `./gradlew evidenceCheck`. Runtime, migration,
|
||||||
migration-свидетельства — отдельные скрипты из `scripts/`.
|
mutation и browser E2E — отдельные скрипты из `scripts/`; baseline —
|
||||||
|
`docs/evidence/baseline-2026-10-27.md`.
|
||||||
- CI merge gate — `.gitlab-ci.yml`: `./gradlew --no-daemon test ktlintCheck detekt evidenceCheck`
|
- CI merge gate — `.gitlab-ci.yml`: `./gradlew --no-daemon test ktlintCheck detekt evidenceCheck`
|
||||||
на push/MR. Runner должен разрешать privileged `docker:dind` для Testcontainers.
|
на push/MR. Runner должен разрешать privileged `docker:dind` для Testcontainers.
|
||||||
|
|
||||||
|
|||||||
@@ -294,9 +294,10 @@ upgrade-тест миграций, видимость активов и deploy-r
|
|||||||
## 7. LDD baseline
|
## 7. LDD baseline
|
||||||
|
|
||||||
После этапа 6 текущая функциональность проверена через LDD-контур:
|
После этапа 6 текущая функциональность проверена через LDD-контур:
|
||||||
реестр `docs/evidence/claims.json` (31 claim, 19 P0 / 12 P1), gate
|
реестр `docs/evidence/claims.json` (34 claim, 19 P0 / 15 P1), gate
|
||||||
`./gradlew evidenceCheck`, upgrade-скрипт и runtime-smoke полного стека.
|
`./gradlew evidenceCheck`, upgrade-скрипт, runtime-smoke, mutation testing
|
||||||
Результат: **31/31 claims proven, P0 gaps = 0**, 267 тестов, upgrade с
|
и браузерный Playwright E2E. Результат: **34/34 claims proven, P0 gaps = 0**,
|
||||||
master-схемы и E2E-поток «админ → группа → курс → преподаватель → лаба»
|
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).
|
[`docs/evidence/baseline-2026-10-27.md`](evidence/baseline-2026-10-27.md).
|
||||||
|
|||||||
@@ -44,16 +44,27 @@
|
|||||||
|
|
||||||
# 4. Проверка upgrade с master-схемы
|
# 4. Проверка upgrade с master-схемы
|
||||||
./scripts/ldd-migration-upgrade.sh
|
./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`.
|
Отчёт: `build/reports/evidence/index.md`.
|
||||||
|
|
||||||
## Правила
|
## Правила
|
||||||
|
|
||||||
1. Новое P0-требование без свидетельства не мержится.
|
1. Новое P0-требование без свидетельства не мержится.
|
||||||
2. Свидетельство должно быть воспроизводимым в CI, а не «проверил руками».
|
2. Свидетельство должно быть воспроизводимым в CI, а не «проверил руками».
|
||||||
3. Тест должен падать при поломке соответствующей логики; для критичных
|
3. Тест должен падать при поломке соответствующей логики. Для критичных
|
||||||
пакетов позже добавим mutation testing.
|
пакетов это измеряется mutation testing: сейчас `CourseAccessService` —
|
||||||
|
75% test strength, `PromotionPlanner` — 69%.
|
||||||
4. Один тест может подтверждать несколько claims, но claim не должен
|
4. Один тест может подтверждать несколько claims, но claim не должен
|
||||||
опираться на тест, который проверяет только реализацию.
|
опираться на тест, который проверяет только реализацию.
|
||||||
5. `limitations` обязателен: LDD не должен создавать иллюзию полного
|
5. `limitations` обязателен: LDD не должен создавать иллюзию полного
|
||||||
@@ -65,12 +76,21 @@
|
|||||||
|
|
||||||
## Текущий baseline
|
## Текущий baseline
|
||||||
|
|
||||||
Первый прогон LDD выполнен 2026-10-27:
|
Первый LDD-цикл выполнен 2026-10-27/28:
|
||||||
|
|
||||||
- 267 автоматических тестов, 0 failures/errors;
|
- **273 автоматических теста**, 0 failures/errors;
|
||||||
- 33 claims: P0 — доступы, повышение, жизненный цикл, профиль/скачивание,
|
- **34 claims**: 19 P0 + 15 P1. P0 — доступы, повышение, жизненный цикл,
|
||||||
материалы/активы, миграция V13, аудит; P1 — группы, авторство, UI,
|
профиль/скачивание, материалы/активы, миграция V13, аудит; P1 — группы,
|
||||||
контракты, импорт, копирование лаб, runtime.
|
авторство, UI, контракты, импорт, копирование лаб, runtime, mutation и
|
||||||
- Runtime-smoke и master-upgrade вынесены в отдельные скрипты.
|
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`.
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
# LDD baseline: 2026-10-27
|
# LDD baseline: 2026-10-27/28
|
||||||
|
|
||||||
Первый прогон доказательной проверки текущей функциональности LMS.
|
Первый и второй LDD-циклы проверки текущей функциональности LMS.
|
||||||
Код приложения в этом прогоне не менялся; добавлены реестр claims, gate
|
Добавлены реестр claims, gate `evidenceCheck`, runtime/migration/mutation
|
||||||
`evidenceCheck`, runtime- и migration-скрипты.
|
скрипты и браузерный E2E на Playwright. В ходе проверки найден и исправлен
|
||||||
|
реальный дефект Jackson 3.
|
||||||
|
|
||||||
## 1. Что проверялось
|
## 1. Что проверялось
|
||||||
|
|
||||||
Реестр: `docs/evidence/claims.json`, 31 утверждение.
|
Реестр: `docs/evidence/claims.json`, **34 утверждения**.
|
||||||
|
|
||||||
| Критичность | Claims | Proven | Gaps |
|
| Критичность | Claims | Proven | Gaps |
|
||||||
|---|---:|---:|---:|
|
|---|---:|---:|---:|
|
||||||
| P0 | 19 | 19 | 0 |
|
| P0 | 19 | 19 | 0 |
|
||||||
| P1 | 12 | 12 | 0 |
|
| P1 | 15 | 15 | 0 |
|
||||||
| **Итого** | **31** | **31** | **0** |
|
| **Итого** | **34** | **34** | **0** |
|
||||||
|
|
||||||
Домены:
|
Домены:
|
||||||
|
|
||||||
@@ -24,8 +25,9 @@
|
|||||||
- материалы и активы;
|
- материалы и активы;
|
||||||
- миграция V13 и полный upgrade с master-схемы;
|
- миграция V13 и полный upgrade с master-схемы;
|
||||||
- аудит: токен, admin-only, сохранность после удаления, representative-хуки;
|
- аудит: токен, admin-only, сохранность после удаления, representative-хуки;
|
||||||
- группы курса, авторство материалов, ведомость, UI/контракты, импорт, копирование лаб;
|
- группы курса, авторство материалов, ведомость, UI/контракты, импорт,
|
||||||
- runtime-smoke полного стека.
|
копирование лабораторных;
|
||||||
|
- runtime-smoke, mutation testing, браузерный E2E.
|
||||||
|
|
||||||
## 2. Команды и результаты
|
## 2. Команды и результаты
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@
|
|||||||
./gradlew test --rerun-tasks
|
./gradlew test --rerun-tasks
|
||||||
```
|
```
|
||||||
|
|
||||||
Результат: **267 тестов, 0 failures, 0 errors, 0 skipped**.
|
Результат: **273 теста, 0 failures, 0 errors, 0 skipped**.
|
||||||
`ktlintCheck` и `detekt` — зелёные.
|
`ktlintCheck` и `detekt` — зелёные.
|
||||||
|
|
||||||
### 2.2. LDD gate
|
### 2.2. LDD gate
|
||||||
@@ -44,7 +46,7 @@
|
|||||||
./gradlew evidenceCheck
|
./gradlew evidenceCheck
|
||||||
```
|
```
|
||||||
|
|
||||||
Результат: **31/31 claims proven, P0 gaps = 0**.
|
Результат: **34/34 claims proven, P0 gaps = 0**.
|
||||||
Отчёт: `build/reports/evidence/index.md`.
|
Отчёт: `build/reports/evidence/index.md`.
|
||||||
|
|
||||||
Gate устроен так:
|
Gate устроен так:
|
||||||
@@ -94,49 +96,94 @@ identity `V4–V10`, academic `V6–V12`, progress `V13`.
|
|||||||
- чужой преподаватель получает `403` на курс, лабу и аудит;
|
- чужой преподаватель получает `403` на курс, лабу и аудит;
|
||||||
- админ видит audit-события `COURSE_CREATE`, `TEACHER_CREATE`,
|
- админ видит audit-события `COURSE_CREATE`, `TEACHER_CREATE`,
|
||||||
`COURSE_TEACHER_ASSIGN`, `COURSE_GROUP_ATTACH`, `LAB_CREATE`;
|
`COURSE_TEACHER_ASSIGN`, `COURSE_GROUP_ATTACH`, `LAB_CREATE`;
|
||||||
- web `/login` отдаёт `200`, публичное дерево материалов доступно, курсовая
|
- web `/login` отдаёт `200`, публичное дерево материалов доступно, курсовые
|
||||||
материалы анонимно — `401`.
|
материалы анонимно — `401`.
|
||||||
|
|
||||||
Результат: **PASS**, evidence: `build/evidence/runtime.json`.
|
Результат: **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. Что это доказывает
|
## 3. Что это доказывает
|
||||||
|
|
||||||
- Критичные P0-инварианты доступа, повышения, жизненного цикла, профиля,
|
- Критичные P0-инварианты доступа, повышения, жизненного цикла, профиля,
|
||||||
материалов, миграции и аудита имеют зелёные автоматические свидетельства.
|
материалов, миграции и аудита имеют зелёные автоматические свидетельства.
|
||||||
- Приложение собирается, мигрируется с master-схемы и поднимается полным
|
- Приложение собирается, мигрирует с master-схемы и поднимается полным
|
||||||
стеком на чистой БД.
|
стеком на чистой БД.
|
||||||
- Ключевой доменный поток «админ → группа → курс → преподаватель → лаба»
|
- Ключевой доменный поток «админ → группа → курс → преподаватель → лаба»
|
||||||
проходит через реальные HTTP/gateway/БД, а не только через mock.
|
проходит через реальные HTTP/gateway/БД и браузер.
|
||||||
- Чужой преподаватель не получает доступ к курсу/лабе/аудиту на реальном стеке.
|
- Чужой преподаватель не получает доступ к курсу/лабе/аудиту на реальном стеке.
|
||||||
- Аудит пишется и читается; upgrade не теряет синтетические данные.
|
- Аудит пишется и читается; upgrade не теряет синтетические данные.
|
||||||
|
- Мутационная прочность критичных компонентов измерена, а не заявлена.
|
||||||
|
- Реальный дефект DTO/Jackson найден именно E2E-контуром и закрыт тестом.
|
||||||
|
|
||||||
## 4. Чего это не доказывает
|
## 4. Чего это не доказывает
|
||||||
|
|
||||||
1. **Нет браузерного E2E.** Thymeleaf-тесты проверяют HTML, но не реальные
|
1. **Нет нагрузочных и конкурентных испытаний.** Advisory locks и гонки
|
||||||
клики/JS/CSRF/редиректы в браузере.
|
|
||||||
2. **Нет нагрузочных и конкурентных испытаний.** Advisory locks и гонки
|
|
||||||
проверены кодом и unit/integration-тестами, но не под нагрузкой.
|
проверены кодом и unit/integration-тестами, но не под нагрузкой.
|
||||||
3. **Нет mutation testing.** Сила тестов измерена косвенно; следующий шаг —
|
2. **Mutation testing не 100%.** Остаются эквивалентные мутанты и
|
||||||
PIT на `CourseAccessService`, `PromotionService`, `StudentProfileService`.
|
Kotlin/Spring-специфичные мутации; PIT harness — JUnit 4, а не JUnit 5.
|
||||||
4. **Нет property-based/model-based проверки повышения.** Один сценарный тест
|
3. **Property-based тесты покрывают не все ветки.** Есть генераторы для
|
||||||
не покрывает все комбинации курсов, степеней и академ-переходов.
|
матрицы доступа и планировщика повышения, но не для транзакционного
|
||||||
|
apply/rollback и конкурентных сценариев.
|
||||||
|
4. **Браузерный E2E — один Chromium и один сценарий на роль.** Нет
|
||||||
|
визуальной регрессии, мобильных размеров, Safari/Firefox.
|
||||||
5. **Legacy-активы без `article_assets` остаются публичными.**
|
5. **Legacy-активы без `article_assets` остаются публичными.**
|
||||||
6. **JWT живёт до 30 дней.** Web перепроверяет статус, прямой API — нет.
|
6. **JWT живёт до 30 дней.** Web перепроверяет статус, прямой API — нет.
|
||||||
7. **Ведущие нули номера группы нормализуются** (`01` → `1`).
|
7. **Ведущие нули номера группы нормализуются** (`01` → `1`).
|
||||||
8. **Нет пагинации/keyset** для части списков и N+1 в отдельных экранах.
|
8. **Нет пагинации/keyset** для части списков и N+1 в отдельных экранах.
|
||||||
9. **Runtime-smoke не входит в unit-CI**; он запускается отдельным скриптом
|
9. **Runtime/mutation/browser E2E не входят в unit-CI**; это release-скрипты.
|
||||||
перед релизом.
|
|
||||||
|
|
||||||
## 5. Вывод
|
## 5. Вывод
|
||||||
|
|
||||||
Текущая функциональность прошла первый LDD-контур: **P0 gaps = 0**,
|
Текущая функциональность прошла LDD-контур: **34/34 claims proven, P0 gaps = 0**,
|
||||||
полный стек и upgrade работают. Это достаточное основание продолжать
|
273 теста, upgrade, mutation baseline и браузерный E2E зелёные. Это
|
||||||
доработки, но не «формальное доказательство всей системы». Следующий цикл
|
достаточное основание продолжать доработки, но не «формальное доказательство
|
||||||
LDD должен добавить:
|
всей системы».
|
||||||
|
|
||||||
1. mutation testing для критичных пакетов;
|
Следующий цикл LDD:
|
||||||
2. property-based тесты повышения и матрицы доступа;
|
|
||||||
3. браузерный E2E (Playwright) для ведомости, профиля и материалов;
|
1. нагрузочный smoke на чтение ведомости/профиля и конкурентный apply/rollback;
|
||||||
4. нагрузочный smoke на чтение ведомости/профиля;
|
2. property-based/model-based тесты транзакционного повышения;
|
||||||
5. автоматический runtime-smoke в release-пайплайне.
|
3. расширение browser E2E (студенческая сдача, публикация оценки, мобильный вид);
|
||||||
|
4. автоматический release-пайплайн с runtime/mutation/browser evidence.
|
||||||
|
|||||||
Reference in New Issue
Block a user