FlakyDetector — мой путь к созданию инструмента для ловли «нестабильных» тестов в Python
В каждой команде есть те самые тесты, которым никто не верит. Они падают «иногда», часто по причине, которую никто не может воспроизвести.
Ты запускаешь тесты — всё зелёное. CI запускает те же тесты — и внезапно падает какая-то ерунда. Разработчик пишет: «У меня работает». QA отвечает: «У нас — нет».
Так я впервые глубоко задумался о феномене flaky-тестов. Эти тесты подрывают доверие к CI, замедляют релизы и крадут часы разработчиков. Поэтому я решил создать инструмент, который сможет:
— находить такие тесты автоматически, — объяснять, что именно в них нестабильно, — и предлагать путь к исправлению.
Так появился FlakyDetector — мой персональный проект, который перерос в полноценный инструмент анализа нестабильных тестов. Ниже — история о том, как я его создавал.
🔥 Зачем вообще ловить flaky-тесты?
Потому что одна “нестабильная” проверка:
- может завалить релиз,
- заставить команду перезапускать CI раз за разом,
- замедлить разработку в 3–5 раз,
- полностью уничтожить доверие к тестам.
Причины у flaky бывают разные:
- гонки в async-коде,
- тайминги и сетевые таймауты,
- зависимость тестов друг от друга,
- глобальное состояние,
- неправильные моки.
Но всё это нужно сначала обнаружить, иначе команда будет просто спорить.
🎯 С чего начался путь
Меня дико раздражало, что CI иногда «падает сам по себе». Логи огромные, тестов тысячи, а времени разбираться у разработчиков — ноль.
Я искал уже готовые инструменты:
- что-то было слишком сложным,
- что-то требовало переписывать весь CI,
- что-то работало только под конкретный тест-раннер.
В итоге я решил: создам собственный инструмент, который решает задачу именно так, как нужно мне.
⚙ Архитектура FlakyDetector: просто о сложном
Чтобы понять, насколько тест «нестабилен», нужно собрать огромную картину:
- Логи CI — ошибки, тайминги, зависшие процессы.
- Анализ кода теста — глобальные переменные, async, моки.
- Статистика последних запусков — где тест падал, сколько раз, почему.
- ML-классификация — тип поведения: race condition? timeout? order dependency?
В итоге архитектура родилась такая:
Но давай по частям.
📥 Модуль Dataset Collector: мозг, который собирает хаос
CI-логи — это ад.
GitHub Actions может дать:
- 200 МБ логов,
- разные форматы вывода,
- rate limit,
- обрезанные строки.
Мне нужно было из хаоса извлечь:
- статус каждого теста,
- время выполнения,
- тип ошибки,
- стабильность за N последних билдов.
Dataset Collector стал первым модулем, который я написал. Он умеет:
- обходить лимиты GitHub API,
- парсить разнородные логи,
- нормализовать события,
- строить статистику по тестам.
🔍 Log Analyzer: объясняет, что именно пошло не так
Тесты падают не просто так.
И чаще всего виноваты:
- AsyncIssue — гонки в event loop,
- TimingIssue — реальные/ложные таймауты,
- NetworkIssue — временная потеря связи,
- OrderDependency — тесты зависят друг от друга,
- GlobalState — кто-то меняет переменную на уровне модуля.
Log Analyzer научился выделять эти паттерны автоматически.
🤖 ML модель: CatBoost классифицирует flaky-поведение
Я не хотел ограничиваться простыми правилами типа:
«Если тест упал с таймаутом → значит этот тест flaky».
Это неправда.
Я собрал датасет и обучил CatBoostClassifier, который анализирует:
- текст ошибки,
- стек-трейс,
- скорость выполнения теста,
- стабильность за последние 20+ запусков,
- влияние порядка тестов.
Модель даёт точность 87.3% — и этого достаточно, чтобы автоматически сортировать тесты по типу нестабильности.
📊 Dashboard: чтобы команда сразу видела картину
Я сделал дашборд на React + Recharts:
- график flaky rate
- топ нестабильных тестов
- рекомендации по каждому тесту
- история ошибок
- вкладка диагностики
- экспорт отчётов
Удобно для QA, для тимлидов и для CI-инженеров.
📈 Результаты
Метрика Значение
Время анализа одного теста < 100 мс
Точность классификации 87.3 %
Поддержка тестов 10 000+
Снижение flaky rate 15–20 %
Ускорение диагностики до 60 %
🔧 Над чем ещё работаю
Проект ещё развивается.
Сейчас в плане:
- привести документацию в полный порядок,
- добавить поддержку Pytest markers,
- расширить анализ async-тестов,
- улучшить визуализацию,
- добавить интеграцию с GitLab CI и Bitbucket,
- вынести модель в отдельный сервис.
Хочу, чтобы FlakyDetector стал полноценным инструментом, который можно использовать в любой Python-команде.
🧠 Итоги
Flaky-тесты — это не просто “разовая неприятность”. Это скрытая угроза стабильности продукта, скорости разработки и нервов команды.
Создание FlakyDetector научило меня:
- понимать природу нестабильного поведения тестов,
- работать с ML на реальных данных,
- строить систему логирования и нормализации,
- проектировать удобные инструменты для разработчиков,
- оптимизировать CI/CD пайплайны.
И самое главное — автоматизировать то, что команды обычно делают вручную.
Если вам знакома проблема flaky-тестов — возможно, вам пригодится мой опыт. А если хотите попробовать FlakyDetector — пишите,
поделюсь.