Проблема нестабильных E2E-тестов не нова. Про флаки, ретраи и «зеленые прогоны» написаны десятки статей, и в каждой есть правильные мысли. Но, как это часто бывает, читать — одно, а заставить это работать в реальном проекте — совсем другое.

Я тоже не искал лёгких путей и пришёл к своим решениям через боль, страдания и разбор бесконечных падений (не повторяйте этот путь, если есть возможность). В этой статье я расскажу, какие подходы помогли нам в команде приблизиться к стабильным E2E-прогонам, которым действительно можно доверять.


Первое, с чего стоит начать — исключить сломанные тесты.

Да, именно так. Нужно исключить все тесты, которые флакают, падают из-за ошибок автотестов или нестабильной среды. Пусть у вас останется один тест, а может не останется ни одного — это нормально. На этом этапе важно не количество, а доверие к результатам.

Будет больно выключать тесты, в которые вы вложили кучу времени и сил. Кажется, будто ты сам себе режешь автоматизацию. Но если тест падает через раз — он уже не выполняет свою основную задачу: давать ответ, всё ли в порядке с системой.

Почему это важно

Тестам, которые регулярно падают без реальных проблем в системе, очень быстро перестают верить.
На их результаты перестают смотреть как на финальное состояние системы — это просто портянка ошибок, которую нужно разбирать, чтобы понять, «что там на самом деле произошло».

А дальше начинается самое неприятное:
автотесты есть, но решения по ним никто не принимает.

Что это даёт на практике

Когда у вас есть пусть маленький, но стабильно зелёный набор E2E-тестов:

  • ими начинают пользоваться другие члены команды — разработчики, аналитики, менеджеры;

  • результат тестов можно понять за минуту: зелёное — всё хорошо, красное — проблема в конкретном месте;

  • такие тесты стали на шаг ближе к встраиванию в CI/CD пайплайн.

Важно: сделать это не разово, а системно

Исключение тестов должно быть не героическим поступком одного автоматизатора, а правилом.

Например:
если тест упал три раза подряд без подтверждённой продуктовой причины — мы исключаем его из основного прогона, помечаем тегом и заводим задачу на исправление.
Без обид, без поисков виноватых — просто гигиена.


Шаг 2. Сделайте ретраи тестов

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

Именно поэтому ретраи — не зло и не костыль, а рабочий инструмент.

Зачем нужны ретраи

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

Как это реализовать

В большинстве случаев ретраи можно включить из коробки:

  • TestNG

  • JUnit 5

Если вы всё ещё используете JUnit 4 — придётся дописать немного своей логики.


Шаг 3. Научите тесты думать

Очень часто при разборе падений E2E-тестов выясняется:
если бы этот сценарий выполнял человек, он бы спокойно прошёл его руками.

Автотест же в этот момент ведёт себя максимально прямолинейно:
что-то пошло не по плану — всё, тест упал.

Проблема не всегда в системе. Часто проблема в том, что тест слишком быстро сдаётся.

Как “думает” ручной тестировщик

Ручной тестировщик редко следует сценарию как робот.
Если кнопка не появилась — он обновит страницу.
Если форма не открылась — попробует зайти другим путём.
Если действие не сработало — проверит альтернативный вариант.

Он знает обходную логику и применяет её.

Что с этим делать в автотестах

Задача автоматизатора в таких ситуациях — научить тест повторять эту логику.

Это не значит писать сложные конструкции на каждый чих.
Это значит:

  • уметь проверять несколько допустимых состояний;

  • корректно обрабатывать альтернативные сценарии;

  • не падать сразу, если система ведёт себя ожидаемо, но не идеально.

Проще говоря — дать тесту больше контекста, а не заставлять его жить в идеальном мире.

Важное замечание

Здесь легко уйти в крайность и превратить тесты в монстров, которые проходят любой сценарий. Так делать не нужно.

Если система ведёт себя неправильно — тест должен падать.
Но если система ведёт себя допустимо, просто чуть иначе — тест должен понимать это.


Шаг 4. Делайте тесты короче

Чем длиннее E2E-тест, тем больше в нём мест, где он может упасть.

Почему длинные тесты — это боль

Каждый дополнительный шаг — это:

  • ещё один запрос,

  • ещё одно ожидание,

  • ещё одна зависимость от состояния системы.

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

Как мы с этим боролись

Мы перестали пытаться проверять всё и сразу в одном тесте.

  • Логин проверяется отдельно.

  • Регистрация проверяется отдельно.

  • Создание данных — отдельно.

Тесты стали короче, понятнее и предсказуемее.

“Но как это будут понимать ручные тестировщики?”

Этот вопрос возникает почти всегда — и он справедливый.
При разбиении сценариев автотесты перестают выглядеть как классические тест-кейсы.

Мы решали это просто:

  • создавали папки с названием бизнес-сценария;

  • внутри хранили тесты, которые проверяют отдельные части этого сценария.

Что это дало

Короткие тесты:

  • падают реже;

  • быстрее выполняются;

  • проще чинятся;

  • легче воспринимаются;

Без взаимодействия с разработкой тут никуда

Чтобы писать короткие E2E-тесты, часто нужны:

  • прямые URL до нужных форм или экранов;

  • ручки для подготовки состояния системы;

  • возможность обходить лишние шаги UI.

Без помощи разработки это сделать сложно, а иногда невозможно.
Но хорошая новость в том, что эти же инструменты часто сильно упрощают и ручное тестирование.


Шаг 5. Взаимодействуйте с разработкой

Стабильные E2E-тесты невозможно построить в вакууме.
Если автоматизация живёт отдельно от разработки — она почти гарантированно будет нестабильной, медленной и неудобной.

Что автоматизатору действительно нужно от разработки

Разработчики редко думают о тестируемости, если их об этом не просить.
И это нормально — это не их основная задача.

Но автоматизатору могут сильно помочь, например:

  • прямые URL до нужных экранов и форм в UI;

  • отдельные test-only эндпоинты для подготовки данных;

  • возможность прокидывать события или управлять их приоритетом;

  • стабильные HTML-атрибуты или тестовые теги для UI-элементов.


Шаг 6. Используйте моки

E2E-тесты нужны для проверки вашего продукта, а не для валидации всего интернета вокруг него.
Поэтому первое, что стоит сделать, если вы хотите стабильности, — перестать проверять в E2E то, на что вы не можете повлиять.

Что стоит мокать в первую очередь

Внешние зависимости:

  • сторонние сервисы;

  • внешние API;

  • любые интеграции, которые живут за пределами вашего контура.

Если внешний сервис лёг, задеградировал или просто ответил медленнее обычного — это не должно ломать ваши E2E-прогоны.

“Но мы же хотим проверить, что всё работает вместе”

Хотите — проверяйте.
Просто не мешайте эти проверки с основными E2E-сценариями.

Хорошая практика:

  • один набор тестов — с моками, стабильный, быстрый;

  • отдельный набор — с реальными интеграциями, реже запускаемый, осознанно нестабильный.

Так вы и интеграции проверите, и основной пайплайн не превратите в лотерею.


Бонус шаг. Запускайте тесты на изолированной среде

Круто, если бы у вас в компании есть возможность поднять изолированную среду, в которой вы сами контролируете версии приложения и внешних интеграций. Среда, в которой никто не накатит, не сломает и не залезет. Но, если честно, есть нюансы:

  • кто-то должен следить за всеми версиями зависимостей;

  • кто-то должен поддерживать среду в актуальном виде;

  • кто-то должен обеспечивать её стабильность.

Вопросов много, а ответов по этому пункту у меня нет. Но не упомянуть такую возможность я не мог.

Для небольшого сервиса и его unit-тестировани или пары микросервисов для интеграционного тестирования такая изоляция работает отлично. А вот системные тесты сюда вписываются сложнее. Если у вас был опыт работы в изолированной среде — велком в комментарии, интересно услышать.


Наверное, я что-то упустил, что-то забыл, но основные пункты, которые мы попробовали и даже те, что не пробовали (см. последний пункт), я описал. Это сработало у нас, сработает и у вас. Пробуйте, экспериментируйте и не бойтесь предлагать новое. Всегда тяжело продвигать изменения туда, где уже устоялись процессы, но чтобы сделать лучше, приходится отказываться от старого.

Всё, что нужно — начать. Маленькими шагами, но регулярно. А дальше вы сами увидите, как это работает и что можно улучшить. Удачи!

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