Files
ss-tools/docs/adr/ADR-0013-coverage-reporting.md
busya 6989bb0bc9 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
2026-06-15 13:40:22 +03:00

6.6 KiB
Raw Blame History

[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]