← Назад к вопросам

Как собираешь статистику с тестов?

2.0 Middle🔥 212 комментариев
#Теория тестирования#Фреймворки тестирования

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сбор и анализ статистики тестов в автоматизации

Сбор статистики — это систематический процесс, который я выстраиваю на нескольких уровнях инфраструктуры. Статистика служит не просто для отчётности, а для принятия решений об улучшении процесса разработки, качества продукта и эффективности самих тестов.

Ключевые метрики, которые я собираю

Я фокусируюсь на метриках, дающих практическую пользу:

  • Статус выполнения: общий процент успешных/проваленных/пропущенных тестов.
  • Время выполнения: общее время прогона, время медленных тестов, динамика изменений.
  • Стабильность тестов (Flaky Rate): процент тестов, которые периодически дают разный результат при тех же условиях.
  • Покрытие (Code Coverage): процент покрытия production-кода тестами (обычно через инструменты вроде JaCoCo, Istanbul).
  • Дефектная эффективность: соотношение количества найденных автоматизацией багов к общему числу багов.
  • Ресурсозатратность: потребление CPU, памяти, время отклика API во время тестов.

Техническая реализация сбора данных

Сбор начинается на уровне фреймворка для тестирования (JUnit, TestNG, pytest, Mocha). Я использую их встроенные механизмы и расширяю их.

1. Использование Listeners/Хуков и отчётов

Почти все фреймворки предоставляют интерфейсы для перехвата событий теста.

// Пример на Java (TestNG)
public class StatisticsListener implements ITestListener {
    private Map<String, TestResult> results = new ConcurrentHashMap<>();

    @Override
    public void onTestSuccess(ITestResult result) {
        results.put(getTestId(result), new TestResult("PASS", result.getEndMillis() - result.getStartMillis()));
    }

    @Override
    public void onTestFailure(ITestResult result) {
        results.put(getTestId(result), new TestResult("FAIL", result.getEndMillis() - result.getStartMillis(), result.getThrowable()));
        // Отправка в систему мониторинга (например, Grafana)
        sendMetric("test_failure", 1, result.getTestClass().getName());
    }
}

Для генерации первичных отчётов я настраиваю плагины:

  • Allure Report: Идеален для детализированных отчётов с шагами, скриншотами, артефактами.
  • ExtentReports: Гибкий и настраиваемый.
  • pytest-html / Mochawesome: Стандартные решения для Python и JS.

2. Интеграция с CI/CD и системы хранения

Сам по себе отчёт в артефактах CI — это уже статистика. Но для анализа трендов данные нужно хранить и агрегировать.

  • CI/CD (Jenkins, GitLab CI, GitHub Actions): Я настраиваю пайплайны на сбор метрик (JUnit-отчёты, время выполнения) и их экспорт.
    # Пример шага в GitLab CI
    test:e2e:
      stage: test
      script:
        - npm run test:e2e
      artifacts:
        when: always
        reports:
          junit: reports/junit.xml
        paths:
          - allure-report/
      after_script:
        # Скрипт для парсинга junit.xml и отправки в базу данных
        - python scripts/send_stats_to_db.py
    
  • Базы данных: Простые метрики (статус, время) отправляю в InfluxDB или TimescaleDB (оптимизированы под временные ряды).
  • Системы мониторинга: Grafana становится единой панелью управления. Я создаю дашборды с графиками успешности прогонов, трендами времени выполнения, тепловыми картами самых частых падений.

3. Расширенная аналитика через собственные скрипты

Часто требуется специфичная логика. Я пишу скрипты-агрегаторы (на Python/Node.js), которые:

  • Парсят XML/JSON отчёты (JUnit, xUnit).
  • Считают flaky-тесты, анализируя историю запусков из CI или базы данных.
  • Коррелируют падения тестов с деплоями новых версий приложения.
    # Пример Python-скрипта для анализа медленных тестов
    import xml.etree.ElementTree as ET
    from collections import defaultdict
    
    tree = ET.parse('test-results.xml')
    root = tree.getroot()
    test_times = defaultdict(float)
    
    for testcase in root.findall('.//testcase'):
        classname = testcase.get('classname')
        name = testcase.get('name')
        time = float(testcase.get('time'))
        test_times[f"{classname}.{name}"] = time
    
    # Топ-10 самых медленных тестов
    slowest = sorted(test_times.items(), key=lambda x: x[1], reverse=True)[:10]
    for test, duration in slowest:
        print(f"{test}: {duration:.2f}s")
    

4. Сбор метрик окружения и приложения

Для полноты картины важно собирать не только метрики тестов, но и контекст, в котором они выполнялись:

  • Версия приложения / commit hash.
  • Параметры окружения: ОС, версия браузера/Docker-образа, ресурсы машины.
  • Метрики SUT (System Under Test): Логи ошибок, метрики производительности (собираются через интеграцию с Prometheus или APM-инструментами).

Пример итогового процесса

  1. Запуск тестов в CI с подключёнными Listeners.
  2. Генерация отчётов Allure/JUnit.
  3. Парсинг отчётов и отправка ключевых метрик (статус, время, имя теста, окружение) в InfluxDB.
  4. Визуализация в Grafana: дашборд с основными графиками и алертами (например, при росте процента падений >10%).
  5. Еженедельный анализ: Отсмотр трендов, выявление flaky-тестов, анализ самых медленных сценариев для оптимизации.

Таким образом, моя система сбора статистики превращает сырые данные выполнения тестов в ценные инсайты для команды: куда направить усилия по стабилизации, какие модуны требуют больше тестового внимания, и как оптимизировать время выполнения пайплайна. Это непрерывный цикл measure -> analyze -> improve.

Как собираешь статистику с тестов? | PrepBro