Начните с риска и oracle, затем выберите самый дешёвый уровень теста, который даст полезное доказательство. Название инструмента само по себе не является стратегией.
Вопросы и ответы
11 подробных ответов
01Какие локаторы есть в Selenium и когда XPath лучше CSS-селектора?
junior
Короткий ответ: Selenium поддерживает восемь стратегий: id, name, className, tagName, linkText, partialLinkText, cssSelector и xpath. CSS быстрее и читаемее, но XPath умеет то, чего CSS не может: подниматься вверх и назад по DOM (ancestor, parent, preceding-sibling) и искать элемент по тексту. В этом вся асимметрия.
Подробно:
- CSS-селектор — стандарт по умолчанию: короткий синтаксис, работает быстрее (браузер оптимизирует CSS-движок), покрывает 90% случаев.
- XPath навигация вверх — только XPath дойдёт от найденного элемента к родителю/предку:
//span[text()='Итого']/ancestor::tr. - XPath по тексту —
//button[text()='Оплатить']илиcontains(text(),'...'); в CSS поиска по текстовому содержимому нет вообще.
| Возможность | CSS | XPath |
|---|---|---|
| Скорость | выше | ниже |
| Читаемость | выше | ниже |
| Вверх по DOM | нет | да |
| Поиск по тексту | нет | да |
| Индекс элемента | :nth-child |
[2] |
⚠️ Частая ошибка: не знать асимметрию и отвечать «XPath мощнее». Мощнее только в навигации вверх и по тексту — во всём остальном по умолчанию берут CSS.
02Чем implicit wait отличается от explicit wait и почему их нельзя смешивать?
middle
Короткий ответ: Implicit wait — это глобальный таймаут поиска элемента на весь драйвер (по умолчанию 0, то есть выключен): драйвер будет ждать появления любого элемента до заданного времени. Explicit wait — это WebDriverWait под конкретное условие для конкретного элемента, опрашивающий состояние примерно каждые 500 мс. Смешивать их нельзя: таймауты складываются непредсказуемо.
Подробно:
- Implicit — задаётся один раз (
driver.implicitly_wait(10)), действует на всеfind_element; ждёт только присутствия элемента в DOM, не проверяет видимость или кликабельность. - Explicit —
WebDriverWait(driver, 10).until(EC.element_to_be_clickable(...)); ждёт нужное состояние, poll interval по умолчанию 500 мс. - Почему не смешивать — при одновременном включении обоих драйвер может суммировать ожидания непредсказуемым образом, и вместо 10 секунд тест ждёт минуты.
| Свойство | Implicit | Explicit |
|---|---|---|
| Область | весь драйвер | один вызов |
| Дефолт | 0 (выключен) | нет |
| Условие | присутствие в DOM | любое (EC) |
| Poll | — | ~500 мс |
⚠️ Частая ошибка: включить implicitly_wait и сверху накидывать WebDriverWait. Правило — выбрать один механизм, обычно explicit, а implicit держать на 0.
03Почему Thread.sleep() в автотестах — антипаттерн и чем его заменить?
middle
Короткий ответ: Thread.sleep() — это статичная пауза на фиксированное время. На быстром окружении она зря тормозит прогон (ждём 5 секунд там, где хватило бы 200 мс), а на медленном — всё равно не хватает, и тест флакает. Замена — условные ожидания, которые опрашивают состояние и продолжают сразу, как только условие выполнено: WebDriverWait + ExpectedConditions в Selenium или встроенный auto-wait в Playwright.
Подробно:
- Проблема — sleep не знает ничего о состоянии страницы; он всегда либо слишком длинный, либо слишком короткий.
- Решение — ожидание по условию:
until(EC.visibility_of_element_located(...))завершается ровно тогда, когда элемент готов.
# Плохо: слепая пауза
time.sleep(5)
driver.find_element(By.ID, "submit").click()
# Хорошо: ждём именно нужное состояние
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "submit"))
).click()
⚠️ Частая ошибка: «тест флакает — поставлю sleep побольше». Это лечит симптом ценой скорости и всё равно не даёт гарантии; правильный ответ — явное ожидание условия.
04Тест падает один раз из пяти прогонов. Как будете чинить?
senior
Короткий ответ: Флакающий тест чинят через системный поиск root-cause, а не через retry. Изолированно прогоняю тест N раз, собираю на падении логи, скриншот и снимок DOM, классифицирую причину и чиню корень. Retry — это маскировка нестабильности, а не решение; это надо проговорить вслух.
Подробно:
- Воспроизвести — гоняю тест изолированно 20–50 раз, ловлю падение и фиксирую частоту.
- Собрать улики — на фейле снимаю скриншот, HTML-дамп DOM, логи браузера и трейс.
- Классифицировать причину — чаще всего одно из пяти:
| Причина | Симптом | Лечение |
|---|---|---|
| Ожидания (race) | элемент не успел появиться | explicit wait по условию |
| Хрупкий локатор | иногда не находит | стабильный data-testid |
| Тест-данные | зависит от чужих данных | изоляция/фикстуры |
| Порядок тестов | падает только в наборе | убрать общее состояние |
| Окружение | падает только в CI | ресурсы, тайминги, сеть |
- Починить корень и проверить — снова гоняю N раз, добиваюсь зелёного стабильно.
⚠️ Частая ошибка: обернуть тест в @Retry(3) и закрыть задачу. Это прячет баг — иногда реальный дефект продукта — и копит технический долг в наборе.
05Какие исключения бросает Selenium и о чём говорит StaleElementReferenceException?
middle
Короткий ответ: Самые частые исключения — NoSuchElementException, StaleElementReferenceException, TimeoutException и ElementNotInteractableException, и каждое привязано к своей причине. StaleElementReferenceException означает, что ссылка на элемент устарела: DOM перерисовался, и старый WebElement больше не указывает на живой узел. Лечится перезапросом элемента, а не оборачиванием всего в try/except.
Подробно:
| Исключение | Причина | Лечение |
|---|---|---|
| NoSuchElement | элемента нет в DOM / неверный локатор | wait на присутствие, проверить селектор |
| StaleElementReference | DOM перерисован, ссылка протухла | заново найти элемент |
| Timeout | условие WebDriverWait не наступило за таймаут |
увеличить таймаут или поправить условие |
| ElementNotInteractable | элемент есть, но скрыт/перекрыт/disabled | wait до clickable, скролл |
Практика для stale: перечитать элемент прямо перед действием, а не хранить старую ссылку через ре-рендер (типично для React/SPA после обновления состояния).
⚠️ Частая ошибка: глушить StaleElementReferenceException через try/except и ретрай в цикле. Это прячет реальную гонку с ре-рендером — правильно перезапросить элемент после того, как DOM устаканился.
06Зачем нужен JavaScriptExecutor и когда его использование — тревожный знак?
middle
Короткий ответ: JavaScriptExecutor выполняет произвольный JS прямо в браузере, когда обычного WebDriver API не хватает: скролл до элемента, клик по перекрытому элементу, доступ в shadow DOM, чтение JS-переменной со страницы. Но клик через JS обходит реальный пользовательский путь — если тест «работает только через JS», это тревожный знак: возможно, вы наткнулись на баг UI.
Подробно:
- Легитимные случаи — скролл (
scrollIntoView), чтение состояния (return document.title), взаимодействие с элементами, до которых WebDriver физически не дотягивается (shadow DOM, хитрые оверлеи). - Красный флаг —
arguments[0].click()вместо обычного клика: WebDriver отказался кликать, потому что элемент невидим/перекрыт/disabled — то есть и реальный пользователь бы не кликнул.
// Скролл — ок
js.executeScript("arguments[0].scrollIntoView(true);", el);
// JS-клик в обход проверок кликабельности — красный флаг
js.executeScript("arguments[0].click();", el);
⚠️ Частая ошибка: «обычный клик не срабатывает — сделаю через JS». Так вы прячете реальный дефект (элемент перекрыт модалкой) и получаете зелёный тест на сломанном UI.
07Что такое Selenium Grid и зачем он нужен?
junior
Короткий ответ: Selenium Grid — это инфраструктура для распределённого параллельного запуска тестов на разных машинах, браузерах и ОС. Классическая архитектура — hub-and-node: хаб принимает запросы и раздаёт их нодам, где реально крутятся браузеры. Ключевое: Grid — это слой исполнения, а не драйвер и не тест-фреймворк.
Подробно:
- Hub — точка входа: получает запрос теста с нужными capabilities (браузер, версия, ОС) и маршрутизирует его на подходящую ноду.
- Node — рабочая машина, где запускается реальный браузер и выполняются команды WebDriver.
- Зачем — параллелить прогон (10 тестов на 10 нодах вместо очереди), покрывать кросс-браузерную и кросс-платформенную матрицу без зоопарка локальных машин.
┌──────────┐
тесты ───► │ HUB │ маршрутизация по capabilities
└────┬─────┘
┌──────────┼──────────┐
┌──┴───┐ ┌──┴────┐ ┌──┴────┐
│Node 1│ │Node 2 │ │Node 3 │
│Chrome│ │Firefox│ │ Edge │
└──────┘ └───────┘ └───────┘
⚠️ Частая ошибка: путать Grid с самим Selenium WebDriver или с тест-раннером (TestNG/pytest). Grid только распределяет исполнение — писать и запускать тесты по-прежнему нужно фреймворком.
08Чем Playwright отличается от Selenium?
middle
Короткий ответ: Playwright автоматически ждёт actionability каждого элемента (видимость, доступность, стабильность) перед действием, поэтому ручные ожидания почти не нужны. Он управляет браузером напрямую через протоколы (CDP и аналоги), а не через цепочку WebDriver, — это быстрее и стабильнее, — и приносит из коробки трейсинг, скриншоты и мокинг сети.
Подробно:
- Auto-wait — перед кликом Playwright сам дожидается, что элемент visible, enabled и stable; explicit
WebDriverWaitпочти не пишут. - Управление браузером — прямой протокол вместо JSON Wire / W3C поверх HTTP; меньше сетевых хопов, меньше флака.
- Из коробки —
trace viewer, авто-скриншоты/видео,page.route()для мокинга сети, авто-ожидания в ассёртах (expect).
| Критерий | Selenium | Playwright |
|---|---|---|
| Ожидания | ручные (WebDriverWait) |
авто-actionability |
| Связь с браузером | WebDriver протокол | прямой (CDP и др.) |
| Трейс/сеть/видео | докручивать | встроено |
| Стандарт | W3C, шире экосистема | новее, единый API |
⚠️ Частая ошибка: тащить в Playwright селениумовскую привычку ручных sleep/wait. Здесь это лишнее и часто вредит — надо полагаться на встроенные авто-ожидания.
09Какими свойствами должен обладать хороший автотест?
middle
Короткий ответ: Хороший автотест описывают мнемоникой FIRST: Fast, Independent, Repeatable, Self-validating, Timely. Плюс детерминизм и отсутствие хардкода данных. На собеседовании интервьюер особенно слушает независимость тестов друг от друга — это реальный вопрос, например в Ozon.
Подробно:
- Fast (быстрый) — прогон не должен занимать вечность, иначе его перестают запускать.
- Independent (независимый) — тест не зависит от других и от порядка запуска; своё состояние готовит и убирает сам.
- Repeatable (повторяемый) — даёт один результат в любом окружении, без привязки к «сегодняшней» дате или чужим данным.
- Self-validating (самопроверяемый) — чёткий pass/fail через ассёрты, без ручного разбора логов.
- Timely (своевременный) — пишется вовремя, рядом с кодом фичи, а не «когда-нибудь потом».
Дополнительно: детерминизм (никаких случайных задержек и гонок) и никакого хардкода тест-данных — генерировать или готовить через фикстуры.
⚠️ Частая ошибка: делать тесты, которые проходят только в определённом порядке из-за общего состояния. Стоит запустить их вразнобой или параллельно — и набор рассыпается.
10Как выбрать стабильный локатор и почему абсолютный XPath — это хрупко?
middle
Короткий ответ: Стабильный локатор опирается на то, что не меняется от рестайлинга вёрстки. Приоритет: data-testid → id → семантический атрибут или роль → короткий относительный CSS. Абсолютный XPath вида /html/body/div[3]/div/span[2] хрупок, потому что ломается от любой вставки или перестановки узла в дереве.
Подробно:
data-testid— атрибут, добавленный специально для тестов; не меняется от дизайна и рефакторинга. Лучший выбор.id— стабилен, если он не автогенерируемый (неid="ember1234").- Семантика/роль —
getByRole,aria-label,name; устойчиво и близко к тому, что видит пользователь. - Короткий относительный CSS — по классу-якорю рядом с элементом.
# Плохо: абсолютный путь — рвётся от любой правки вёрстки
/html/body/div[3]/div/form/div[2]/button
# Хорошо: якорь на тестовый атрибут
[data-testid="checkout-submit"]
Бонус к ответу: договориться с разработчиками проставлять data-testid — это дешевле, чем бороться с хрупкими селекторами.
⚠️ Частая ошибка: копировать «Copy full XPath» из DevTools. Такой абсолютный путь зелёный сегодня и красный после ближайшего изменения разметки.
11Чем Selenide удобнее «голого» Selenium?
junior
Короткий ответ: Selenide — это обёртка над Selenium, которая закрывает его болевые места: умные ожидания по умолчанию (таймаут 4 секунды в каждом $/$$), лаконичный синтаксис вроде $("...").shouldBe(visible), автоскриншоты при падении и автоматическое управление драйвером. В российских Java-командах Selenide почти стандарт, и вопрос про него реально задают.
Подробно:
- Умные ожидания — каждый поиск и ассёрт сам ждёт до 4 секунд, поэтому явные
WebDriverWaitиsleepпочти не нужны — это убирает главный источник флака. - Лаконичный API —
shouldBe,shouldHaveвместо ручных проверок; код читается как описание поведения. - Диагностика — автоскриншот и HTML-дамп на падении из коробки.
- Драйвер — Selenide сам поднимает и закрывает WebDriver.
// Голый Selenium: ручной wait + разбор состояния
new WebDriverWait(driver, Duration.ofSeconds(4))
.until(ExpectedConditions.elementToBeClickable(By.id("submit")))
.click();
// Selenide: ожидание встроено
$("#submit").shouldBe(visible).click();
⚠️ Частая ошибка: считать Selenide отдельным «конкурентом» Selenium. Это обёртка поверх Selenium WebDriver — она не заменяет его, а делает удобнее.
Источники
Источники и редакционная политика
Материалы RecallDeck сопоставлены с официальной документацией и открытыми публикациями компаний, когда первичный источник доступен. Мы не связаны с упомянутыми работодателями, не публикуем конфиденциальные задания и не продаём места в подборках. Формат найма может меняться — уточняйте его у рекрутера.
От чтения к воспроизведению
Отрепетируйте полный цикл интервью.
RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.