Нестабильные (flaky) тесты создают постоянные трудности для тестировщиков. Такие тесты не отражают состояния тестируемой системы и подрывают доверие к тестовому набору.

Вооружившись лучшими практиками, нестабильность можно свести к минимуму, но полностью избавиться от неё крайне трудно. Чтобы лучше её контролировать, нужны инструменты, позволяющие выявлять нестабильные тесты — например, Allure Report. В этом руководстве мы посмотрим, как Allure работает с нестабильными тестами:

  • Исследуем, как устроена история тестов

  • Разберёмся, как история позволяет определять нестабильные тесты

  • Настроим перезапуск тестов

Эту функциональность мы рассмотрим на примере PyTest, но все те же принципы работают и с другими фреймворками.

Заодно мы познакомимся с Allure 3. Многие из вас наверняка пользуются Allure 2 — в третьей версии (помимо прочих изменений) работа с нестабильными тестами стала гораздо удобнее, в особенности настройка истории тестов.

1. Подготовка

Код демонстрации

https://github.com/rattus-aristarchus/guide-allure-reruns

Список зависимостей

pytest: 9.0.2

allure-pytest: 2.15.3

Установка

Перед началом работы нужно установить:

Затем необходимо создать новый проект Python или открыть существующий.

В файл зависимостей (requirements.txt) добавим следующее:

pytest==9.0.2
allure-pytest==2.15.3

Установим зависимости:

pip install -r requirements.txt

2. Пробные тесты

Чтобы было на чём продемонстрировать возможности Allure, нам понадобится один нестабильный тест — и, для контраста, один стабильный:

import random


def test_stable():
    """
    Стабильный тест
    """
    assert 1 == 1

    
def test_flaky():
    """
    Нестабильный тест: орёл — проходит, решка — не проходит
    """
    assert random.randint(0, 1) == 1

Поместим их в файл test/flaky_test.py.

3. История тестов в Allure Report

Для обнаружения нестабильных тестов Allure нужна история прошлых запусков. Эта история хранится в специальном файле .jsonl.

Если Allure запускается на CI-сервере (например, Jenkins или GitHub Actions), история генерируется автоматически с помощью соответствующих плагинов. В ТестОпс — централизованной платформе на основе Allure — для работы с историей дополнительная настройка не требуется.

При локальном запуске Allure 2 история требовала много ручной работы; в Allure 3 она была автоматизирована, и теперь достаточно указать путь к файлу истории в настройках.

Создадим файл настроек allurerc.mjs в корне проекта:

export default {
  // Имя отчёта
  name: "Работа с нестабильными тестами",
  // Путь к папке с отчётом
  output: "./allure-report",
  // Путь к файлу с историей тестов
  historyPath: "./history.jsonl",
  // Плагины
  plugins: {
    // awesome - базовый плагин для Allure 3
    awesome: {
      options: {
        reportLanguage: "ru",
      },
    },
  },
};

Архитектура Allure 3 построена на плагинах; базовая функциональность инструмента содержится в плагине awesome.

Убедимся, что история заработала; для этого выполним тесты.

Тесты и генерация отчёта (а также создание файла истории) в Allure 3 выполняются одной командой: npx allure run -- <команда_запуска_тестов>.

В нашем случае команда выглядит так:

npx allure run --config=./allurerc.mjs -- "pytest --alluredir allure-results"

В флаге --config для allure run указываем путь к файлу конфигурации.

Выполним команду несколько раз, чтобы появилась история. В файле history.jsonl должно возникнуть несколько новых элементов — по одному на каждый запуск:

Файл истории
Файл истории

Чтобы посмотреть отчёт, выполним allure open:

Так выглядит Allure 3
Так выглядит Allure 3

Кликнем имя теста (например, test_flaky), и перейдём на вкладку История:

История запусков
История запусков

Как видим, история работает и прошлые запуски отображаются.

4. Определение нестабильных тестов

Allure определяет, что тест нестабилен, одним из двух способов:

  1. Получает информацию от фреймворка (так, например, в JUnit 5). Этот случай сейчас мы рассматривать не будем, потому что он не автоматический.

  2. Автоматически на основе истории запусков.

Во втором случае критерии нестабильного теста такие:

  • Тест падал как минимум один раз за последние 5 запусков.

  • После падения тест хотя бы один раз проходил успешно.

  • В текущем запуске у теста статус Неуспешный или Сломанный.

Тесты, подходящие под критерии, можно легко определить на вкладке Результаты по специальному значку:

Значок нестабильного теста
Значок нестабильного теста

При желании можно отфильтровать дерево тестов, чтобы оно отображало только нестабильные тесты:

Фильтрация нестабильных тестов
Фильтрация нестабильных тестов

К этой функциональности Allure можно добавить инструмент, запускающий тесты в случайном порядке — например, плагин для PyTest pytest-random-order. Результаты тестов не должны зависеть от выполнения других тестов, поэтому это хорошая проверка на стабильность.

5. Повторы (Retries)

Итак, мы нашли «моргающий» тест; что с ним делать?

В идеале нужно проанализировать причины нестабильности и исправить тест. Это требует времени и внимания. Сейчас в этом могут помочь нейросети — но поработать всё равно придётся.

Тест можно вручную поместить в «карантин» — добавить в коде аннотацию @pytest.mark.xfail. Но так мы не решаем проблему, а откладываем в долгий ящик: неработающие тесты будут копиться, пока рано или поздно, когда контекст уже давно выветрился из памяти, их снова придётся разгребать.

Наконец, тест часто перезапускают, чтобы исключить ложные падения. Allure 3 позволяет делать это «из коробки».

Для этого к команде запуска тестов достаточно добавить флаг --rerun с аргументом максимального количества перезапусков:

npx allure run --config=.\allurerc.mjs --rerun 3 -- "pytest --alluredir allure-results"

Итоговый отчёт будет выглядеть так:

Перезапущенный тест в Allur
Перезапущенный тест в Allur

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

Вкладка «Перезапуски»
Вкладка «Перезапуски»

6. Заключение

Нестабильные тесты — известная проблема, и индустрия разработала множество инструментов для борьбы с ней. Allure 3 позволяет:

  • Легко настроить отображение истории запусков тестов

  • Автоматически обнаруживать нестабильные тесты

  • Перезапускать упавшие тесты

Про Allure 3 можно писать много — благодаря модульной архитектуре у него огромное пространство для экспериментов, и у нас наверняка будут ещё поводы поговорить о нём.