feat(coverage): add coverage-summary script, README section, ADR-0013

- scripts/coverage-summary.sh — unified coverage summary generator
  Runs pytest+coverage (unit/integration) and vitest+coverage,
  parses results, generates single HTML report with both stacks.
  Supports --unit, --backend-only, --frontend-only, --output-dir.
- README.md — add 'Покрытие кода' sub-section under Тестирование
- docs/adr/ADR-0013-coverage-reporting.md — architectural decision record
This commit is contained in:
2026-06-15 13:40:22 +03:00
parent e8021c8f74
commit 6989bb0bc9
3 changed files with 654 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
# [DEF:ADR-0013:ADR]
# @STATUS ACTIVE
# @PURPOSE Зафиксировать архитектурное решение об автоматизации сбора покрытия кода, генерации сводного HTML-отчёта и интеграции скрипта `scripts/coverage-summary.sh` в процесс разработки.
# @RELATION DEPENDS_ON -> [ADR-0001-module-layout]
# @RELATION DEPENDS_ON -> [ADR-0006-frontend-architecture]
# @RELATION DEPENDS_ON -> [ADR-0011-async-backend]
# @RELATION DEPENDS_ON -> [ADR-0012-superset-testcontainers]
# @RATIONALE Проект ss-tools состоит из двух независимых стеков (Python/FastAPI backend, Svelte frontend), каждый со своим инструментом покрытия (coverage.py, vitest/v8). Разработчику приходится запускать их по отдельности и вручную сопоставлять результаты. Без единого скрипта: (a) покрытие проверяется нерегулярно, (b) регрессии покрытия остаются незамеченными до CI, (c) новые разработчики тратят время на изучение двух разных команд.
# @RATIONALE Единый скрипт `scripts/coverage-summary.sh` решает эти проблемы: (a) одна команда для полного цикла, (b) сводный HTML с визуальным статусом каждого стека, (c) парсинг результатов тестов и процентов покрытия в машиночитаемом виде, (d) детализированные HTML-отчёты coverage по каждому стеку.
## Решение
Создан скрипт `scripts/coverage-summary.sh`, который:
### 1. Запуск backend-тестов
- **Режим integration** (по умолчанию): `pytest tests/integration/ --run-integration --cov=src` — требует Docker + Testcontainers PostgreSQL
- **Режим unit**: `pytest tests/ --ignore=tests/integration/ --cov=src` — SQLite на tempfile, без Docker
- Парсинг: строка `TOTAL` из coverage.py → statements, missed, процент
- Парсинг: строка вида `X passed, Y failed` → количество тестов
### 2. Запуск frontend-тестов
- `vitest run --coverage --coverage.reportOnFailure` с v8 provider
- Парсинг: строка `All files | % Stmts | % Branch | % Funcs | % Lines` из текстового репортера
- Парсинг: строка `Tests: X passed, Y failed` → количество тестов
### 3. Генерация сводного HTML
Единый `index.html` со:
- Status bar: Overall / Backend / Frontend (цвета: success/failed)
- Карточка каждого стека: тесты (pass/total), покрытие (%), statements/missed
- Для frontend: Statements, Branch, Functions, Lines с цветовой индикацией (зелёный ≥80%, оранжевый 50-79%, красный <50%)
- Сводная таблица Combined Summary
- Ссылки на детализированные HTML-отчёты coverage каждого стека
- Timestamp генерации
### 4. Режимы запуска
| Флаг | Описание |
|------|----------|
| (без флагов) | Backend integration + frontend |
| `--unit` | Backend unit (SQLite) + frontend |
| `--backend-only` | Только backend |
| `--frontend-only` | Только frontend |
| `--backend-only --unit` | Только backend unit |
| `--skip-integration` | Только frontend (backend пропущен) |
| `--output-dir <path>` | Директория отчёта (по умолч. `coverage-summary/`) |
## Альтернативы
### @REJECTED Интеграция в CI (GitHub Actions) на данном этапе
Отвергнуто, так как проект ещё не имеет CI-инфраструктуры. Скрипт спроектирован так, чтобы его можно было легко запускать как локально, так и в CI. Добавление CI-шага будет выполнено отдельным ADR.
### @REJECTED Единый инструмент покрытия (pytest-cov + vitest в одном плагине)
Отвергнуто из-за разной природы инструментов: coverage.py и vitest/v8 несовместимы на уровне форматов данных. Вместо этого используется гибридный подход: каждый инструмент генерирует свой HTML, а сводка собирается в единый индекс.
### @REJECTED Замена vitest/v8 на istanbul
Отвергнуто: v8 provider работает быстрее (`@vitest/coverage-v8` уже установлен). Istanbul (`@vitest/coverage-istanbul`) доступен как опция, но не является default.
## Детали реализации
### Парсинг coverage.py
```
TOTAL 34845 18112 48%
```
Парсятся через `awk`: statements (колонка 2), missed (колонка 3), процент (колонка 4).
### Парсинг vitest
```
All files | 99.25 | 87.39 | 98.91 | 99.48
```
Парсятся через `awk -F'|'`: Stmts, Branch, Funcs, Lines.
### Файловая структура отчёта
```
coverage-summary/
├── index.html # Сводный отчёт
├── backend/ # HTML от coverage.py
│ ├── index.html
│ ├── ...
│ └── pytest_output.txt # Raw вывод pytest
└── frontend/ # HTML от vitest --coverage
├── index.html
├── ...
└── vitest_output.txt # Raw вывод vitest
```
### Зависимости
- Backend: Python 3.9+, `.venv` с установленными `pytest-cov` (входит в `requirements-dev.txt`)
- Frontend: Node.js 18+, `node_modules` с `@vitest/coverage-v8` (входит в `devDependencies`)
- Docker: только для `--unit` не требуется; для integration требуется Docker Engine 24+
- Скрипт написан на bash, не требует дополнительных утилит (кроме стандартных `grep`, `awk`, `sed`)
## Статус
**ACTIVE** скрипт создан и протестирован. Используется для локальной проверки покрытия.
# [/DEF:ADR-0013:ADR]