Как подходишь к написанию локаторов в UI-автотестах?

«Как подходишь к написанию локаторов в UI-автотестах?» — вопрос из категории Selenium и Selenide, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Моя стратегия основана на поиске стабильных, семантических и читаемых способов найти элемент. Приоритеты всегда следующие:

1. Идеальный вариант: Атрибуты для тестов. Договариваюсь с фронтенд-разработчиками о добавлении специальных data-testid или data-qa атрибутов. Это самый надежный способ.

    // Selenide (Java)
    $(by("data-testid", "submit-button")).click();

2. Стандартные семантические атрибуты. Если data-* нет, ищу id, name или ARIA-атрибуты (role, aria-label).

3. CSS-селекторы по классам или атрибутам. Выбираю классы, которые отражают состояние или функцию элемента (например, .btn-primary), а не стилевые или сгенерированные (.jss-123).

    $(".cart .total-price").shouldHave(text("100$"));

4. XPath — крайняя мера. Использую только когда другие способы не работают, и пишу максимально простые и устойчивые к изменениям вёрстки пути. Избегаю индексов ([1]) и сложных переходов.

    // Плохо: хрупкий XPath
    $("//div[3]/section[2]/div/button[1]");
    // Лучше: XPath по тексту или уникальному атрибуту
    $(byXpath("//button[contains(text(), 'Confirm Order')]"));

Мой рабочий процесс:

  • Использую паттерн Page Object. Все локаторы хранятся в одном месте — классах, представляющих страницы или компоненты. Это позволяет обновить локатор в одном месте, если вёрстка изменилась.
  • Пишу явные ожидания (explicit waits). Никогда не использую Thread.sleep(). В Selenide это встроено, в Selenium WebDriver использую WebDriverWait.
    // Selenium WebDriver с явным ожиданием
    new WebDriverWait(driver, Duration.ofSeconds(10))
        .until(ExpectedConditions.visibilityOfElementLocated(By.id("result")));
  • Комментирую сложные локаторы, объясняя, почему был выбран именно такой путь, особенно если пришлось использовать XPath.