diff --git a/README.md b/README.md index f6b648f..102e609 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ progress `:8083`, web `:8090`. Интерфейс: `http://localhost:8090`. ./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 && npx playwright install chromium) +./scripts/ldd-release.sh # полный release gate: test/upgrade/mutation/runtime/E2E ``` - `ktlint` отвечает за формат, `detekt` — за качество (сложность, вложенность, ошибки). diff --git a/docs/16-stage6-report.md b/docs/16-stage6-report.md index 8c6fb82..07de1c1 100644 --- a/docs/16-stage6-report.md +++ b/docs/16-stage6-report.md @@ -294,10 +294,11 @@ upgrade-тест миграций, видимость активов и deploy-r ## 7. LDD baseline После этапа 6 текущая функциональность проверена через LDD-контур: -реестр `docs/evidence/claims.json` (34 claim, 19 P0 / 15 P1), gate +реестр `docs/evidence/claims.json` (37 claim, 20 P0 / 17 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 нашёл и закрыл реальный дефект +и браузерный Playwright E2E. Результат: **37/37 claims proven, P0 gaps = 0**, +276 тестов; mutation strength `CourseAccessService` 75%, +`PromotionPlanner` 69%; browser E2E 4/4; конкурентные apply/rollback и +нагрузочный smoke (p95 0.945 c) зелёные. E2E нашёл и закрыл реальный дефект Jackson 3/Kotlin defaults. Подробности и остаточные ограничения — [`docs/evidence/baseline-2026-10-27.md`](evidence/baseline-2026-10-27.md). diff --git a/docs/evidence/README.md b/docs/evidence/README.md index 40ec4a2..94acf09 100644 --- a/docs/evidence/README.md +++ b/docs/evidence/README.md @@ -50,6 +50,9 @@ # 6. Браузерный E2E (Playwright + Chromium) ./scripts/ldd-browser.sh + +# 7. Полный release gate +./scripts/ldd-release.sh ``` Для E2E один раз установите зависимости и браузер: `cd e2e && npm install && npx playwright install chromium`. @@ -78,14 +81,14 @@ Platform 6 из Spring Boot 4. Первый LDD-цикл выполнен 2026-10-27/28: -- **273 автоматических теста**, 0 failures/errors; -- **34 claims**: 19 P0 + 15 P1. P0 — доступы, повышение, жизненный цикл, +- **276 автоматических тестов**, 0 failures/errors; +- **37 claims**: 20 P0 + 17 P1. P0 — доступы, повышение, жизненный цикл, профиль/скачивание, материалы/активы, миграция V13, аудит; P1 — группы, авторство, UI, контракты, импорт, копирование лаб, runtime, mutation и browser E2E; - mutation testing: `CourseAccessService` 75% test strength, `PromotionPlanner` 69%; -- Playwright: 3 сценария (admin, teacher, student/anonymous), все зелёные; +- Playwright: 4 сценария (admin, teacher, student/anonymous, сдача+mobile), все зелёные; - runtime-smoke, master-upgrade, mutation и browser E2E вынесены в отдельные скрипты. diff --git a/docs/evidence/baseline-2026-10-27.md b/docs/evidence/baseline-2026-10-27.md index 4963c35..e7c1bc0 100644 --- a/docs/evidence/baseline-2026-10-27.md +++ b/docs/evidence/baseline-2026-10-27.md @@ -7,13 +7,13 @@ ## 1. Что проверялось -Реестр: `docs/evidence/claims.json`, **34 утверждения**. +Реестр: `docs/evidence/claims.json`, **37 утверждений**. | Критичность | Claims | Proven | Gaps | |---|---:|---:|---:| -| P0 | 19 | 19 | 0 | -| P1 | 15 | 15 | 0 | -| **Итого** | **34** | **34** | **0** | +| P0 | 20 | 20 | 0 | +| P1 | 17 | 17 | 0 | +| **Итого** | **37** | **37** | **0** | Домены: @@ -37,7 +37,7 @@ ./gradlew test --rerun-tasks ``` -Результат: **273 теста, 0 failures, 0 errors, 0 skipped**. +Результат: **276 тестов, 0 failures, 0 errors, 0 skipped**. `ktlintCheck` и `detekt` — зелёные. ### 2.2. LDD gate @@ -46,7 +46,7 @@ ./gradlew evidenceCheck ``` -Результат: **34/34 claims proven, P0 gaps = 0**. +Результат: **37/37 claims proven, P0 gaps = 0**. Отчёт: `build/reports/evidence/index.md`. Gate устроен так: @@ -133,9 +133,28 @@ Playwright/Chromium на полном стеке, одноразовая БД: - anonymous: `/admin/audit` → `/login`; - student: вход, `/admin/audit` → `/student`, `/learn/course/{no}`. -Результат: **3/3 passed**, evidence: `build/evidence/browser.json`. +Результат: **4/4 passed**, evidence: `build/evidence/browser.json`. +Дополнительно проверены сдача файла студентом и mobile-размер teacher-страницы. -### 2.7. Найденный дефект +### 2.7. Конкурентные apply/rollback + +Добавлен `PromotionConcurrencyIntegrationTest` (без `@Transactional`, два потока, +advisory lock): два одновременных apply идемпотентны и пишут history один раз; +два одновременных rollback дают ровно один успех и один `ConflictException`, +состояние восстанавливается один раз. + +### 2.8. Нагрузочный smoke + +`ldd-runtime.sh` выполняет 100 чтений (10 workers) курса, лаб, профиля и аудита: +**0 ошибок, avg 0.141 c, p95 0.945 c** (порог p95 < 2 c). + +### 2.9. Release gate + +`./scripts/ldd-release.sh` последовательно запускает тесты/линтеры, upgrade, +mutation, runtime и browser E2E, затем финальный `evidenceCheck`. +В `.gitlab-ci.yml` добавлен ручной job `release-evidence` с Chromium/Node. + +### 2.10. Найденный дефект Первый browser E2E упал на создании студента: API вернул `400`, потому что Jackson 3 не применял Kotlin-модуль, и DTO с default-значениями требовали все @@ -159,15 +178,15 @@ optional json fields`. ## 4. Чего это не доказывает -1. **Нет нагрузочных и конкурентных испытаний.** Advisory locks и гонки - проверены кодом и unit/integration-тестами, но не под нагрузкой. -2. **Mutation testing не 100%.** Остаются эквивалентные мутанты и +1. **Mutation testing не 100%.** Остаются эквивалентные мутанты и Kotlin/Spring-специфичные мутации; PIT harness — JUnit 4, а не JUnit 5. -3. **Property-based тесты покрывают не все ветки.** Есть генераторы для - матрицы доступа и планировщика повышения, но не для транзакционного - apply/rollback и конкурентных сценариев. -4. **Браузерный E2E — один Chromium и один сценарий на роль.** Нет - визуальной регрессии, мобильных размеров, Safari/Firefox. +2. **Property-based тесты покрывают не все ветки.** Есть генераторы для + матрицы доступа, планировщика и 10 транзакционных apply/rollback-кейсов, + но не для всех сочетаний полей и распределённой нагрузки. +3. **Браузерный E2E — один Chromium и 4 сценария.** Нет визуальной регрессии, + Safari/Firefox и полного мобильного набора страниц. +4. **Нагрузочный smoke — не benchmark.** Одна машина, синтетические данные, + без SLA production. 5. **Legacy-активы без `article_assets` остаются публичными.** 6. **JWT живёт до 30 дней.** Web перепроверяет статус, прямой API — нет. 7. **Ведущие нули номера группы нормализуются** (`01` → `1`). @@ -176,14 +195,15 @@ optional json fields`. ## 5. Вывод -Текущая функциональность прошла LDD-контур: **34/34 claims proven, P0 gaps = 0**, +Текущая функциональность прошла LDD-контур: **37/37 claims proven, P0 gaps = 0**, 273 теста, upgrade, mutation baseline и браузерный E2E зелёные. Это достаточное основание продолжать доработки, но не «формальное доказательство всей системы». Следующий цикл LDD: -1. нагрузочный smoke на чтение ведомости/профиля и конкурентный apply/rollback; -2. property-based/model-based тесты транзакционного повышения; -3. расширение browser E2E (студенческая сдача, публикация оценки, мобильный вид); -4. автоматический release-пайплайн с runtime/mutation/browser evidence. +1. расширить browser E2E на публикацию оценки и остальные мобильные страницы; +2. добавить нагрузочный профиль с реалистичным объёмом групп/студентов; +3. закрыть известные продуктовые риски: legacy-активы, JWT 30 дней, ведущие + нули, пагинация/N+1; +4. сделать release-evidence job обязательным для тегов. diff --git a/docs/evidence/claims.json b/docs/evidence/claims.json index c141ada..49d5509 100644 --- a/docs/evidence/claims.json +++ b/docs/evidence/claims.json @@ -488,16 +488,56 @@ }, { "id": "LDD-BROWSER-001", - "title": "Браузерный E2E админа, преподавателя и студента", + "title": "Браузерный E2E админа, преподавателя и студента, включая сдачу и mobile", "criticality": "P1", "status": "active", "requirement": "docs/evidence/README.md", - "claim": "Playwright на реальном стеке: admin видит курс и аудит, teacher открывает курс/ведомость/профиль и создаёт главу, аноним и студент не попадают в админку.", + "claim": "Playwright на реальном стеке: admin видит курс и аудит; teacher открывает курс/ведомость/профиль, создаёт главу и видит mobile-вид; student сдаёт файл; аноним и студент не попадают в админку.", "oracle": "Playwright assertions на DOM/URL", "runtime": [ "browser.e2e" ], - "limitations": "Один Chromium, один сценарий на роль; визуальная регрессия и мобильные размеры не проверяются." + "limitations": "4 сценария, один Chromium; нет визуальной регрессии и Safari/Firefox." + }, + { + "id": "LDD-RUNTIME-002", + "title": "Нагрузочный smoke чтения курса, лаб, профиля и аудита", + "criticality": "P1", + "status": "active", + "requirement": "docs/evidence/README.md", + "claim": "100 параллельных чтений (10 workers) через gateway дают 0 ошибок и p95 < 2 c.", + "oracle": "HTTP status + latency percentiles", + "runtime": [ + "runtime.load_gradebook_profile" + ], + "limitations": "Smoke, не benchmark; одна машина и синтетические данные, без SLA production." + }, + { + "id": "LDD-PROM-006", + "title": "Конкурентные apply/rollback одного запуска повышения", + "criticality": "P0", + "status": "active", + "requirement": "docs/07-groups-courses.md, §7", + "claim": "Два одновременных apply не дублируют историю; два одновременных rollback дают ровно один успех и один конфликт, состояние восстанавливается один раз.", + "oracle": "Результаты двух потоков, количество APPLY/ROLLBACK и history", + "evidence": [ + "ru.ysu.lms.identity.promotion.PromotionConcurrencyIntegrationTest#concurrent apply of one run is idempotent and writes history once()", + "ru.ysu.lms.identity.promotion.PromotionConcurrencyIntegrationTest#concurrent rollback allows exactly one rollback and restores once()" + ], + "limitations": "Два потока в одном JVM; распределённая нагрузка и несколько инстансов проверяются advisory lock-ом, но не chaos-тестом." + }, + { + "id": "LDD-PROM-007", + "title": "Транзакционный apply/rollback на сгенерированных когортах", + "criticality": "P1", + "status": "active", + "requirement": "docs/07-groups-courses.md, §7", + "claim": "Для 10 сгенерированных когорт apply приводит группу к плану, а rollback возвращает точный before-state и активный статус студента.", + "oracle": "Сравнение состояния группы/студента до, после apply и после rollback", + "evidence": [ + "ru.ysu.lms.identity.promotion.PromotionApplyRollbackPropertyTest#generated cohorts apply to plan and rollback to before-state()" + ], + "limitations": "10 детерминированных сценариев в одной транзакции; не заменяет property-генератор по всем полям." } ] } \ No newline at end of file