Как реализована организация поиска элементов и какие ожидания используются?
Что проверяют
Умеете ли вы писать стабильные UI-автотесты: выбирать надёжные локаторы и ждать нужного состояния страницы, а не фиксированное время. Следом почти всегда спрашивают, чем implicit wait отличается от explicit и почему их не смешивают.
Как отвечать
Локаторы перечисляйте в порядке предпочтения:
- тестовые атрибуты:
data-testidпо договорённости с разработкой, не меняются от редизайна; - id и name: хороши, если стабильны и не генерируются фреймворком;
- CSS-селекторы: короткие и быстрые, по атрибутам, а не по цепочке классов из вёрстки;
- XPath: когда нужен поиск по тексту или переход к родителю, но только относительный (
//button[text()='Сохранить']), без абсолютного пути отhtml; - Page Object: локаторы собраны в классах страниц, тест вызывает методы вроде
loginPage.submit(), и при правке вёрстки меняется одно место.
Про ожидания в Selenium 4:
- implicit wait:
implicitlyWait(Duration.ofSeconds(10)), глобальный таймаут для каждогоfindElement. Умеет только дождаться появления элемента в DOM; - explicit wait:
new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.elementToBeClickable(locator)). Ждёт конкретного условия: видимости, кликабельности, исчезновения лоадера; - FluentWait: тот же explicit с настройкой интервала опроса и списка игнорируемых исключений.
Варианты с числом секунд и TimeUnit в Selenium 4 устарели, нужен Duration. В Playwright задача решена иначе: локаторы ленивые, перед действием выполняются проверки actionability (видим, стабилен, включён, принимает события), а web-first проверки вроде expect(locator).toBeVisible() сами повторяются до таймаута, по умолчанию 5 секунд.
Где спотыкаются
Ставят Thread.sleep. Тест становится медленным на быстром стенде и всё равно падает на медленном.
Смешивают implicit и explicit waits. Документация Selenium прямо предупреждает, что тогда время ожидания непредсказуемо.
Ждут только присутствия элемента в DOM, а потом кликают по нему, пока он перекрыт лоадером или ещё анимируется. В итоге ловят ElementClickInterceptedException, а после перерисовки StaleElementReferenceException.