githubEdit

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') не упадёт при анимации появления.

Диагностика

  1. Документировать нестабильный тест: когда падает, как часто, в каком окружении

  2. Проверить логи, скриншоты, видео прогона (Playwright автоматически записывает при падении)

  3. Запустить тест 10–20 раз изолированно — воспроизвести нестабильность

  4. В 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 из коробки.

Статистика

По данным тестировщиков, основные причины нестабильности по «сложности разбора»:

  1. Асинхронные операции (async wait)

  2. Многопоточность и shared state

  3. Неправильный порядок запуска тестов

  4. Аппаратные проблемы (сеть, память)

Как говорил вице-президент Unity3D Алан Берд: «Нестабильные тесты хуже, чем вообще без тестов» — они создают ложный сигнал и убивают доверие к автоматизации.

Источники

Дополнительные материалы

Last updated