Сценарий 07: Покрытие тестами

Сценарий 07: Покрытие тестами

Инженер по качеству, выявляющий непротестированные участки кода, импортирующий данные выполнения покрытия и получающий рекомендации по тестам на основе CPG.

Быстрый старт

# Выберите сценарий "Покрытие тестами"
/select 07

Поиск пробелов в покрытии

Выявление непротестированных функций

Обработчик по умолчанию использует эвристическое обнаружение: функции, у которых нет вызовов из test_* функций в графе вызовов, считаются непротестированными.

> Какие функции не покрыты тестами?

+-------------- Пробелы в покрытии ----------------+
| Функции без прямых тестов:                       |
|                                                  |
| Критические (executor):                         |
|   - ExecParallelHashJoinNewBatch()               |
|   - ExecReScanGather()                           |
|                                                  |
| Высокий приоритет (storage):                     |
|   - heap_lock_updated_tuple()                    |
|   - heap_abort_speculative()                     |
|                                                  |
| Всего непротестированных: 234 функции            |
| Оценка покрытия: 78%                             |
| Режим обнаружения: Эвристика                     |
+--------------------------------------------------+

Определение приоритетов тестирования

> Какие непротестированные функции оказывают наибольшее влияние?

+-------------- Список приоритетов ----------------+
| Высокое влияние + отсутствие тестов:             |
|                                                  |
| 1. heap_lock_updated_tuple()                     |
|    Влияние: Целостность транзакций               |
|    Количество вызовов: 23                        |
|                                                  |
| 2. ExecParallelHashJoinNewBatch()                |
|    Влияние: Корректность параллельных запросов   |
|    Количество вызовов: 8                         |
|                                                  |
| 3. AtEOXact_RelationCache()                      |
|    Влияние: Согласованность кеша                 |
|    Количество вызовов: 4                         |
+--------------------------------------------------+

Поиск непротестированных путей обработки ошибок

> Найти непротестированные пути обработки ошибок
> Показать точки входа без тестов

Импорт покрытия времени выполнения

Импортируйте данные покрытия из внешних инструментов для включения гибридного обнаружения (данные выполнения + эвристика).

Поддерживаемые форматы

Формат Инструмент Тип файла
pytest-cov pytest-cov (--cov-report=json) JSON
lcov gcov / lcov / geninfo Текст (.info, .lcov)
cobertura Cobertura, JaCoCo, coverage.py XML XML

Команды CLI

# Импорт JSON-отчёта pytest-cov
python -m src.cli coverage import --file coverage.json --format pytest-cov --db data/projects/postgres.duckdb

# Импорт lcov trace файла
python -m src.cli coverage import --file lcov.info --format lcov

# Импорт Cobertura XML (например, из Java/C# инструментов)
python -m src.cli coverage import --file coverage.xml --format cobertura --source-root /project

# Просмотр импортированных данных
python -m src.cli coverage show
python -m src.cli coverage show --uncovered-only

Как это работает

  1. Парсер читает отчёт покрытия и извлекает построчные данные по каждому файлу
  2. Импортёр добавляет колонку coverage_percent в nodes_method (если отсутствует)
  3. Каждый метод сопоставляется с данными покрытия через суффиксное сопоставление имени файла и пересечение диапазона строк метода с покрытыми строками
  4. coverage_percent вычисляется как покрытые_строки_в_диапазоне / всего_строк_в_диапазоне * 100

Нормализация путей: Отчёты покрытия часто содержат абсолютные пути, а CPG хранит относительные. Импортёр нормализует пути (убирает ./, конвертирует обратные слэши) и использует суффиксное сопоставление. Параметр --source-root позволяет обрезать общий префикс для лучшего сопоставления.

Результат импорта

+-------------- Результат импорта покрытия --------+
| Формат: pytest-cov                               |
| Методов обновлено: 1 247 / 3 891                  |
| Файлов сопоставлено: 89 / 112                    |
+--------------------------------------------------+

Гибридное обнаружение

После импорта данных выполнения запросы на непротестированный код автоматически переключаются в гибридный режим:

  • Методы с coverage_percent < 1.0 помечаются по данные выполнения-данным
  • Методы с NULL coverage_percent (нет данных выполнения) используют эвристическое обнаружение по вызовам тестов
  • Каждый кандидат получает метку detection_method: "runtime" или "heuristic"
  • Оценка покрытия использует AVG(coverage_percent) из данных выполнения вместо эвристического подсчёта
> Найти непротестированный код

+------------- Пробелы в покрытии (Гибрид) --------+
| Метод             | Обнаружение | Покрытие | ...  |
|-------------------|-------------|----------|------|
| parse_query()     | Данные выполнения     | 0.0%     | ...  |
| exec_plan()       | Данные выполнения     | 12.5%    | ...  |
| helper_func()     | Эвристика   | ---      | ...  |
|                                                   |
| Режим обнаружения: Данные выполнения + Эвристика            |
| Оценка покрытия: 62.3% (по данным выполнения)        |
+---------------------------------------------------+

Обратная совместимость: Если данные покрытия не были импортированы, обработчик работает идентично эвристическому режиму. Проверка _has_coverage_column() гарантирует отсутствие изменений в поведении.


Рекомендации тестов на основе CPG

Для каждого непротестированного метода (топ-20 по критичности) обработчик анализирует CPG и генерирует конкретные рекомендации по тестированию.

Анализ покрытия веток

Подсчитывает управляющие структуры (IF, FOR, WHILE, SWITCH) из nodes_control_structure и оценивает количество тестовых сценариев, необходимых для покрытия веток.

> Найти непротестированный код

### `parse_query`
1. Добавьте 8 тестовых сценариев для покрытия веток (IF: 3, FOR: 1, SWITCH: 1)
2. Протестируйте граничные значения параметра `query_len` (zero, negative, max, min)
3. Протестируйте обработку ошибок: 2 try/catch блока, 4 return

Анализ граничных значений параметров

Сопоставляет типы параметров из nodes_param с рекомендациями по граничным значениям:

Тип Граничные тесты
int, long, size_t, float zero, negative, max, min
char*, string, str empty, null, very long, special chars
Указатели (*, ptr) null pointer
bool true, false
Вариативные параметры zero args, one arg, many args

Анализ путей ошибок

Подсчитывает блоки TRY в nodes_control_structure и операторы RETURN в nodes_return. Множественные операторы return указывают на пути обработки ошибок, требующие тестирования.


Генерация тестовых случаев

Обработчик генерации тестов предоставляет детальные рекомендации для конкретных функций на основе анализа графа вызовов.

> Сгенерировать тестовые случаи для heap_insert

+------------- Тестовые случаи ----------------------+
|                                                    |
| Функция: heap_insert()                             |
| Файл: src/backend/access/heap/heapam.c:2156        |
|                                                    |
| Стратегия тестового покрытия:                      |
|   Модульные тесты: Тестируйте heap_insert          |
|     изолированно, мокируя 5 зависимостей           |
|   Интеграционные тесты: Тестируйте heap_insert     |
|     через 23 вызывающие функции                    |
|   Граничные случаи: Тестируйте граничные условия,  |
|     null-ввод, обработку ошибок                    |
|                                                    |
| Зависимости для мокирования:                       |
|   - RelationGetBufferForTuple()                    |
|   - heap_prepare_insert()                          |
|   - XLogInsert()                                   |
|                                                    |
| Тестовые сценарии из вызывающих функций:           |
|   - simple_heap_insert() использует heap_insert... |
|   - toast_save_datum() использует heap_insert...   |
+----------------------------------------------------+

Примеры запросов

Обнаружение непротестированного кода: - “Какие функции не покрыты тестами?” - “Найти непротестированный код” - “Показать функции без тестов” - “Какой код не покрыт тестами?”

Приоритизация тестирования: - “Какие критические функции нужно протестировать в первую очередь?” - “Что нужно протестировать в первую очередь?” - “Приоритет тестирования”

Генерация тестов: - “Сгенерировать тестовые случаи для [function_name]” - “Создать тесты для [function_name]” - “Какие граничные случаи следует протестировать в [function_name]?”

Обзор покрытия: - “Показать пробелы в покрытии” - “Отчёт покрытия” - “Как улучшить тестовое покрытие?”

Связанные сценарии