Flaky tests
Flaky-тест — нестабильный, ненадёжный тест, который без изменений в коде то проходит, то падает. Это не просто неудобство: нестабильные тесты подрывают доверие ко всему тестовому суиту и замедляют доставку. Когда команда привыкает перезапускать упавший тест вместо расследования, это сигнал системной проблемы.
Определение
Flaky-тест (Flaky Test) — тест, который при одинаковом состоянии системы и одинаковом коде иногда проходит, иногда падает. Само слово «flaky» (хлопчатый, рассыпающийся) передаёт непредсказуемость результата.
Причины
Асинхронность и тайминги
Самая распространённая причина: тест ожидает элемент или результат асинхронной операции с фиксированным sleep() вместо умного ожидания готовности. Решение — использовать встроенные механизмы ожидания фреймворка.
Неправильная инициализация и очистка данных
Тест зависит от состояния, которое оставил предыдущий тест. При параллельном запуске это проявляется особенно часто. Каждый тест должен самостоятельно создавать нужные данные и очищать состояние после себя.
Неустойчивые локаторы
XPATH-локаторы, зависящие от позиции элемента в DOM, ломаются при изменении разметки. Предпочтительны data-testid, aria-label, role-атрибуты.
Параллельное выполнение и shared state
Тесты, изменяющие одни и те же данные в БД или одного тестового пользователя, конфликтуют при параллельном запуске.
Внешние зависимости
Нестабильное сетевое соединение, медленный внешний API, недоступная база данных. Идеальная тестовая среда — «герметичная»: без внешних зависимостей (моки, Testcontainers, WireMock).
Аппаратные и системные проблемы
Нехватка памяти, медленный диск, неправильно настроенные ресурсы фреймворка.
Автоматическое ожидание как профилактика
Современные фреймворки устраняют целый класс timing-проблем через умное ожидание:
Playwright auto-waiting — перед каждым действием Playwright автоматически проверяет actionability: элемент должен быть visible, enabled, stable (не анимируется), attached to DOM. sleep() для ожидания элементов не нужен.
Cypress retry-ability — assertion-команды автоматически ретраят до тех пор, пока условие не выполнится или не истечёт timeout. cy.get('.button').should('be.visible') не упадёт при анимации появления.
Диагностика
Документировать нестабильный тест: когда падает, как часто, в каком окружении
Проверить логи, скриншоты, видео прогона (Playwright автоматически записывает при падении)
Запустить тест 10–20 раз изолированно — воспроизвести нестабильность
В 90% случаев причина ясна из артефактов прогона
Управление flaky-тестами в CI
Паттерн quarantine
Нестабильный тест помечается как карантинный: он продолжает запускаться, но не блокирует пайплайн. Команда получает уведомление и разбирает проблему по расписанию, не в режиме блокировки PR.
BuildPulse
SaaS-сервис для автоматического отслеживания flaky-тестов. Интегрируется с GitHub Actions/CircleCI/Jenkins через upload junit-xml артефактов. Определяет нестабильные тесты по истории 50+ запусков, автоматически создаёт GitHub Issues.
Currents.dev
Платформа оркестрации для Playwright и Cypress. Dashboard с историей тестов, flakiness score, аналитика по веткам и воркерам. Поддерживает quarantine mode из коробки.
Статистика
По данным тестировщиков, основные причины нестабильности по «сложности разбора»:
Асинхронные операции (async wait)
Многопоточность и shared state
Неправильный порядок запуска тестов
Аппаратные проблемы (сеть, память)
Как говорил вице-президент Unity3D Алан Берд: «Нестабильные тесты хуже, чем вообще без тестов» — они создают ложный сигнал и убивают доверие к автоматизации.
Источники
Дополнительные материалы
Flaky-тесты: Откуда ноги растут. Опыт Uber — кейс масштабной диагностики
Blog: Flaky Testing — системный взгляд на проблему
Last updated