← Назад к вопросам

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

2.0 Middle🔥 201 комментариев
#Теория тестирования

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Мой подход к написанию локаторов

Как опытный QA Automation инженер, я рассматриваю локаторы не просто как технические селекторы для взаимодействия с элементами на странице, а как стратегические объекты, от качества которых напрямую зависит стабильность, поддерживаемость и скорость выполнения тестов. Мой подход основан на многоуровневой системе приоритетов и принципах "устойчивого локаторостроения".

Иерархия приоритетов локаторов

Я строго следую следующему порядку (от наиболее предпочтительного к наименее):

  1. ID — если элемент имеет уникальный и стабильный id, это всегда первый и лучший выбор. Он создан именно для этой цели.

    <!-- Идеально -->
    <button id="submit-payment">Оплатить</button>
    
    # В коде
    submit_button = driver.find_element(By.ID, "submit-payment")
    
  2. Data-атрибуты (data-testid, data-qa, data-cy) — специально предназначены для тестов. Их главное преимущество в отделении логики тестирования от презентационного слоя (CSS) и бизнес-логики (ID могут использоваться скриптами). Я активно пропагандирую их внедрение в процессе разработки.

    <!-- Отлично. Устойчив к рефакторингу CSS и JS. -->
    <div data-testid="user-profile-avatar"></div>
    
    // Использование в Playwright
    await page.locator('[data-testid="user-profile-avatar"]').click();
    
  3. **ARIA.

  4. CSS Selectors — мощный и гибкий инструмент, но требующий аккуратности. Мои правила:

    *   **Избегаю абсолютных путей** (`div > nav > ul > li > a`): хрупкие и ломаются при малейшем изменении верстки.
    *   **Предпочитаю семантические комбинации** классов и атрибутов: `.primary-button[type="submit"]`.
    *   **Использую псевдоклассы с умом** (`:nth-of-type()`) только когда это единственный вариант, и обязательно добавляю комментарий.
```css
/* Плохо: хрупкий и перегруженный */
#content > div.main > form > div.buttons > button.btn-primary

/* Хорошо: лаконичный и семантический */
button.btn-primary[aria-label="Отправить форму"]
```

5. XPath — мой инструмент "последней надежды". Я применяю его только когда все предыдущие способы недоступны, и всегда в осмысленной, нехрупкой форме:

    *   **НИКОГДА** не использую XPath, основанные на абсолютных позициях в DOM (`/html/body/div[5]/div[2]/span`).
    *   **Предпочитаю относительные пути** и поиск по атрибутам или тексту, когда это осмысленно (`//button[contains(text(), 'Сохранить')]`).
    *   Помню, что XPath может быть медленнее на сложных страницах.

Ключевые принципы и практики

  • Уникальность и точность: Локатор должен находить один и только один элемент в рамках контекста поиска. Я всегда проверяю это в DevTools (Ctrl+F в инспекторе элементов).
  • Устойчивость к изменениям: Локатор должен пережить мелкие рефакторинги верстки. Избегаю привязки к структуре, родительским элементам, CSS-классам, которые могут меняться для стилей (например .col-md-3, .pretty-font).
  • Читаемость и поддерживаемость: Имя локатора в переменной или Page Object должно быть семантическим (login_button, а не btn1). В сложных проектах я выношу локаторы в отдельные конфигурационные файлы или классы Page Object, что позволяет обновить их в одном месте при изменении UI.
  • Сотрудничество с разработчиками: Самый эффективный способ — договориться с фронтенд-разработчиками о добавлении data-testid на ключевые элементы. Это инвестиция в стабильность автотестов, которая окупается сторицей, сокращая время на поддержку и "борьбу с флакингом".
  • Динамические данные: Для элементов с динамически генерируемыми ID или текстом (например, user-1283) я использую частичные совпадения: [id^="user-"] в CSS или contains(@id, 'user-') в XPath.

Пример в архитектуре Page Object

// Пример на Java с Selenium
public class LoginPage {
    // Стабильные локаторы, вынесенные в константы
    private final By usernameInput = By.id("username");
    private final By passwordInput = By.cssSelector("[data-testid='password-field']");
    private final By submitButton = By.xpath("//button[text()='Войти']");

    public void login(String user, String pass) {
        driver.findElement(usernameInput).sendKeys(user);
        driver.findElement(passwordInput).sendKeys(pass);
        driver.findElement(submitButton).click();
    }
}

Итог: Мой подход — это баланс между максимальной устойчивостью локатора и его производительностью. Я начинаю с переговоров с разработчиками о data-* атрибутах, использую ID где они есть, и только в крайних случаях создаю сложные CSS/XPath селекторы, документируя причину такого выбора. Это превращает поддержку локаторов из рутины в управляемый и предсказуемый процесс.

Как подходишь к написанию локатора? | PrepBro