Ответ
Одной из самых сложных задач была полная реорганизация и стабилизация набора E2E-тестов для крупного веб-приложения с активно меняющимся интерфейсом. Тесты были написаны на Selenium, но их стабильность была ниже 50%, а поддержка занимала огромное время.
Проблемы, с которыми столкнулся:
- Хрупкие локаторы: Тесты падали из-за изменений в
idилиclassэлементов. - Асинхронная загрузка: Отсутствие корректных ожиданий приводило к
NoSuchElementException. - Отсутствие структуры: Код тестов был плохо организован, с дублированием логики.
- Нет изоляции: Падение одного теста каскадом влияло на другие из-за общего состояния.
Мои действия и решения:
-
Внедрение Page Object Model (POM) и паттернов:
- Рефакторил код, выделяя логику работы со страницами в отдельные классы.
-
Использовал паттерн Loadable Component для явных ожиданий загрузки страницы.
// Пример Page Object с явным ожиданием загрузки public class LoginPage extends BasePage { private By usernameField = By.id("username"); private By passwordField = By.id("password"); private By submitButton = By.cssSelector("button[type='submit']"); @Override protected void isLoaded() throws Error { // Ждём, пока ключевые элементы станут видимыми wait.until(ExpectedConditions.visibilityOfElementLocated(usernameField)); wait.until(ExpectedConditions.visibilityOfElementLocated(submitButton)); } public HomePage login(String user, String pass) { driver.findElement(usernameField).sendKeys(user); driver.findElement(passwordField).sendKeys(pass); driver.findElement(submitButton).click(); return new HomePage(driver); } }
-
Улучшение стратегии локаторов:
- Заменил абсолютные XPath и изменчивые
idна стабильныеdata-test-idатрибуты, которые я договорился с фронтенд-разработчиками добавлять к ключевым элементам. - Стал использовать CSS-селекторы по роли и атрибутам (например,
[aria-label='Search']).
- Заменил абсолютные XPath и изменчивые
-
Настройка умных ожиданий и retry-логики:
- Полностью убрал
Thread.sleep(). - Внедрил кастомные ожидания для сложных условий (например, ожидание исчезновения лоадера и появления контента).
- Добавил retry-механизм на уровне фреймворка (TestNG/IUnit) только для специфичных, подверженных флакючности проверок.
- Полностью убрал
-
Создание надёжной инфраструктуры:
- Настроил изоляцию тестов через сброс состояния БД перед каждым тестом.
- Внедрил параллельный запуск тестов в Docker-контейнерах для скорости.
- Интегрировал сбор скриншотов и логов при падении для быстрой отладки.
Результат: За 3 месяца стабильность тестового прогона выросла с ~45% до 95%. Время выполнения набора из 200+ E2E-тестов сократилось на 60% благодаря параллелизации. Время, затрачиваемое на поддержку и «починку» тестов после каждого релиза, уменьшилось в разы. Это позволило команде увереннее проводить регрессионное тестирование и быстрее выпускать обновления.