Selenium, Playwright и «плавающие» тесты
Даже если вы не автоматизатор, от middle-кандидата ждут понимания, как устроены UI-тесты и почему они «плавают».
Flaky-тест — тест, который на одном и том же коде то падает, то проходит. Он опаснее отсутствующего теста: команда перестаёт доверять всему набору.
Вопрос 1: «Чем Playwright отличается от Selenium?»
Что на самом деле проверяет интервьюер
Ориентируетесь ли вы в инструментах и понимаете ли, что разница не в «моде», а в архитектуре.
Развёрнутый ответ
| Критерий | Selenium WebDriver | Playwright |
| Управление браузером | по протоколу WebDriver, через драйвер | напрямую по протоколу браузера (CDP и аналоги) |
| Ожидания | явные и неявные, настраиваются вручную | авто-ожидание готовности элемента встроено |
| Экосистема | очень зрелая, любой язык, стандарт W3C | моложе, но «из коробки» трассировка, видео, скриншоты, перехват сети |
| Параллельность | через Selenium Grid | встроенные контексты браузера, изоляция сессий |
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# явное ожидание вместо time.sleep
button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='pay-button']"))
)
button.click()
// Playwright: ожидание встроено в действие
await page.getByTestId('pay-button').click();
await expect(page.getByText('Заказ оплачен')).toBeVisible();
Оба примера решают одну задачу, но во втором ожидание не пишется руками — это и есть главная практическая разница. Код помечен как незапускаемый: обе библиотеки внешние и требуют настоящего браузера.
Вопрос 2: «Какие локаторы выбирать и что такое Page Object?»
Развёрнутый ответ
Порядок предпочтения локаторов от лучшего к худшему:
- Специальный атрибут для тестов —
data-testid. Не меняется при редизайне, потому что существует только ради тестов. - Доступные роли и тексты — «кнопка с названием Оплатить». Заодно проверяет доступность интерфейса.
- Стабильный id, если он действительно стабилен, а не сгенерирован фреймворком.
- CSS-селектор по осмысленным классам.
- XPath по структуре вроде
/div[2]/div[3]/span— худший вариант: ломается от любой правки вёрстки.
Page Object — паттерн, при котором страница описывается классом: локаторы и действия внутри, тест — снаружи. Смысл в том, что при изменении вёрстки правится один класс, а не пятьдесят тестов. Тест при этом читается как сценарий на человеческом языке, а не как набор селекторов.
Вопрос 3: «Тест падает через раз. Что делать?»
Что на самом деле проверяет интервьюер
Не предложите ли вы «перезапустить и забыть» — самый вредный ответ в этом блоке.
Развёрнутый ответ
Типовые причины нестабильности и лечение:
- Гонки и ожидания:
time.sleep(2)вместо ожидания условия. Лечится явными ожиданиями конкретного состояния элемента. - Зависимость от данных: тест рассчитывает на пользователя, которого удалил другой тест. Лечится генерацией своих данных и очисткой после прогона.
- Зависимость от порядка: тест 5 работает только после теста 4. Тесты должны быть независимыми.
- Внешние сервисы: реальный платёжный шлюз отвечает нестабильно. Лечится моками и sandbox-окружением.
- Общее состояние и параллельность: два теста меняют одну и ту же запись. Лечится изоляцией — свой аккаунт на тест.
- Время и локаль: тест падает после полуночи или на другом часовом поясе. Лечится фиксацией времени и локали.
Организационная часть ответа не менее важна: flaky-тест нужно пометить и завести на него задачу, а не глушить перезапуском. Автоматический retry маскирует настоящие плавающие дефекты продукта — а они, между прочим, точно так же «плавают» у пользователей.
Типичные ошибки кандидатов
- Предлагают лечить нестабильность увеличением
sleep— это замедляет прогон и не устраняет причину. - Ставят автоматический retry по умолчанию и считают проблему решённой.
- Используют XPath по структуре и жалуются, что тесты ломаются от любой правки вёрстки.
- Пишут тесты, зависящие друг от друга и от порядка выполнения.
- Считают Playwright «заменой Selenium во всём» — выбор зависит от стека команды, языка и требований к поддержке браузеров.
Как ответить кратко
Selenium управляет браузером по стандарту WebDriver, у него огромная экосистема и поддержка любых языков, но ожидания нужно писать руками. Playwright работает по протоколу браузера напрямую, авто-ожидания и трассировка встроены, параллельность — через изолированные контексты. Локаторы выбираю в порядке устойчивости: data-testid, затем роль и текст, затем стабильный id и CSS; XPath по структуре — последний вариант. Страницы описываю паттерном Page Object, чтобы при редизайне править один класс, а не все тесты. Flaky-тесты не глушу перезапусками: ищу причину — sleep вместо ожидания условия, зависимость от данных или порядка, внешние сервисы, общее состояние при параллельном прогоне, привязка ко времени и локали — и завожу на нестабильный тест отдельную задачу.