Как стать автором
Обновить

Локаторы. Стратегии поиска веб-элементов

Уровень сложностиСредний
Время на прочтение15 мин
Количество просмотров3.4K

Какой бы инструмент вы ни выбрали для автоматизации тестирования, все они будут искать элементы с помощью локаторов, и обычно это означает, что вы, как тестировщик, должны их создавать используя селекторы. Какие бывают локаторы, как они выглядят, чем отличаются, какие лучше использовать, а какие избегать и почему, ответы прочтете здесь.
Примеры скриптов покажу на Playwright и Cypress.

Способы локаторов могут быть разными, но в сухом остатке есть только два типа —
CSS и XPath, их вариации и удобные сокращения. Все локаторы строятся на основе DOM и работают с селекторами для поиска элементов.

Элемент — это сам HTML‑объект на странице, например, кнопка «Отправить».

<button id="submit" class="btn">Отправить</button>

Селектор — это способ найти этот элемент в DOM, например:

  • #submit (по id),

  • .btn (по классу),

  • 'button' (по тегу).

Локатор использует этот селектор, например:

await page.locator('#submit').click(); // Playwright
cy.get('#submit').click(); // Cypress

Базовые локаторы

Тестовые атрибуты считаются лучшей практикой
Тестовые атрибуты считаются лучшей практикой

Тестовые атрибуты отличаются от других локаторов тем, что они специально добавляются в код для тестирования и не зависят от изменений в верстке.

<button id="submit" class="btn" data-test="submit-btn">Submit</button>
  • id="submit" может измениться.

  • class="btn" может измениться при изменении стилей.

  • data-test="submit-btn" добавлен специально для тестирования и остается стабильным.

await page.locator('[data-test="submit-btn"]').click(); // Playwright

Атрибуты указываются в квадратных скобках [ ]
Это стандарт CSS‑селекторов и так фреймворки понимают, что мы ищем именно атрибут. Тестовые атрибуты считаются лучшей практикой для авто‑тестов взаимодействующих с UI.
В прошлой статье я уже рекомендовала предложить вашей команде правила для добавления уникальных атрибутов ко всем ключевым элементам, сделать это частью командной работы и документации.

Идентификаторы (id) - это лучший тип локаторов.

Согласно стандартам HTML, атрибут id должен иметь уникальное значение на каждой конкретной странице. Таким образом, локатор, использующий id для идентификации, будет однозначно определять один целевой элемент.

В Playwright и Cypress символ # используется для обозначения id, потому что они следуют стандарту CSS‑селекторов. Всякий раз, когда мне нужно написать локатор, без тестового атрибута, я в первую очередь ищу атрибут id. Если у элемента есть такой атрибут, то мой локатор будет очень простым.

const { test, expect } = require('@playwright/test');

test('Локатор по id в Playwright', async ({ page }) => {
    await page.goto('https://example.com/login');

    // Находим поле ввода по id и вводим данные
    await page.locator('#username').fill('test_user');
    await page.locator('#password').fill('secure_password');

    // Кликаем кнопку входа
    await page.locator('#login-button').click();

    // Проверяем, что после входа появилось приветствие
    await expect(page.locator('#welcome')).toHaveText('Welcome, test_user!');
});

Убедитесь только, что id действительно используется на странице уникальным образом. Это можно проверить с помощью простого поиска в источнике с помощью DevTools.

  • Браузеры: нажать F12 или Ctrl + Shift + I или Cmd + Option + I на macOS.

  • Или: Щелкнуть правой кнопкой мыши по элементу.

  • Дальше: Нажать «Просмотреть код» (Inspect).

    1. Открыть вкладку Elements.

    2. Скопировать id элемента в буфер.

    3. Нажать Ctrl + F (Cmd + F на macOS) для поиска.

    4. Ввести id="your‑id" (замените your‑id на нужный).

    • Если результат 1 то все хорошо.

    • Если > 1, значит id повторяется, это баг.

В общем и целом, советую так же проверять любой селектор, чтобы убедиться, что он точно указывает на нужный элемент, является уникальным и стабильным. Проверка стабильности локатора в DevTools — это про то, чтобы убедиться, что он не изменится например, при перезагрузке страницы и переключении языковой версии сайта. Популярные проверки, остается ли селектор валидным:

  • Перезагрузить страницу (F5).

  • Убедиться, что селектор не содержит динамических атрибутов.

  • Проверить, меняется ли локатор при разных действиях (например, переключение вкладок, прокрутка, изменение состояния).

  • Попробовать открыть сайт в анонимном режиме или другом браузере.

  • Изменить размер экрана (Ctrl + Shift + M в DevTools, эмулировать мобильное устройство).

  • Переключить язык, если сайт поддерживает мультиязычность, и убедиться, что локатор остается рабочим.

Атрибуты name - еще один хороший локатор.

Атрибут name используется в элементах ввода (input, text‑area, select, button) для передачи данных на сервер. Каждый input в форме должен иметь уникальное значение name.

 // HTML
<input type="text" name="firstName">
<input type="text" name="lastName">
  
// Playwright
await page.locator('[name="firstName"]').fill('firstNameTest');
await page.locator('[name="lastName"]').fill('lastNameTest');

Он также группирует radio и checkbox: у radio, name должен быть одинаковым и выбирается один вариант, а у checkbox — тоже одинаковым, но можно выбрать несколько.

<input type="checkbox" name="hobby" value="reading"> Чтение 
<input type="checkbox" name="hobby" value="sports"> Спорт

//Сервер получит hobby=reading&hobby=sports, если выбраны оба.

CSS class name - это третий базовый локатор.

Имена классов определяют стиль CSS для HTML‑элементов. Однако, они также могут служить идентификаторами. Классы в CSS начинаются с точки (.).
У элемента в HTML может быть одно имя класса, несколько имён классов или не быть ни одного.

<div class="class1 class2 class3">Тут несколько классов</div>

Кроме того, имена классов не обязательно должны быть уникальными для каждого элемента. Одно имя класса может использоваться несколькими элементами. Это полезно при поиске набора элементов, например списка результатов поиска.

// CSS
.class2 // Этот селектор выберет все элементы с классом class2

Идентификаторы(id), входные имена (name) и имена классов (class name) — самые простые в использовании локаторы. Я всегда стараюсь сначала найти такие локаторы, прежде чем переходить к более сложным. Их легко найти на странице, если они там есть, и не нужно долго думать, какой написать локатор. Однако, использование в чистом виде, для элементов, у которых ID или классы генерируются динамически, например id="button-12345", приведет к падению тестов при обновлении страницы, ведь для элемента сгенерируется новый id. В такой ситуации, применю более продвинутый тип локаторов и буду использовать частичные совпадения в CSS‑селекторах или XPath. Дальше подробнее о селекторах CSS и XPath локаторах.

Локаторы основанные на CSS селекторах.

Селекторы CSS — это шаблоны, которые используются для выбора элементов на веб‑странице. Они позволяют сказать браузеру или инструменту автоматизации таких как Playwright и Cypress: «Эй, найди мне вот этот элемент на странице!»

В ситуации с динамическим id="button-12345", пример локатора на CSS для Cypress:

cy.get('button[id^="button-"]').click(); 
// ID начинается с "button-"

В ситуации с динамическим id="button-12345", пример на Playwright для XPath:

await page.click('//button[contains(@id, 'button-')]'); 
// ID начинается с "button-"

Примеры CSS-селектора

Простые селекторы выбирают элементы на основе тега элемента, идентификатора и класса. В таблице приведу примеры также с основными символами и конструкциями в CSS‑селекторах. Обратите внимание на знаки, символы и их участие в синтаксисе.

Селектор

Пример

Описание

1

Type Selector.
Селектор по тегу. Выбирает все элементы с указанным тегом.

button

Выберет все кнопки на странице с тегом <button>.

2

ID Selector.
Селектор по ID. Выбирает элемент с указанным ID, начинаются с решетки (#).

#username

Выберет элемент с ID username.

3

Class Selector.
Селектор по классу. Выбирает элементы с указанным классом, начинаются с точки.

.submit-button

Выберет все элементы с классом submit-button.

4

Attribute Selector.
Селектор по атрибуту. Выбирает элементы, у которых есть определенный атрибут
или атрибут с конкретным значением, заключается в квадратные скобки []

[type="submit"]

Выберет все элементы с атрибутом type="submit".

5

Descendant Selector.
Селектор по вложенности. Выберет все элементы внутри другого элемента.

div .submit-button

выберет элементы с классом submit-button, что находятся внутри <div>.

6

Pseudo-classes.
Селектор по псевдоклассам. Позволяет выбирать элементы в определенном состоянии.

button:hover

Выберет кнопку, когда на нее наведен курсор.

7

Pseudo-elements. Селектор по псевдоэлементу (::)
Выбирает часть элемента (например, ::before, ::after).

p::first-line

Выберет первую строку текста в параграфе.

8

Child Selector.
Селектор по дочернему элементу (>).

ul > li

Этот селектор выберет только те <li>, которые являются прямыми детьми <ul>.

9

Селектор по нескольким условиям. Можно комбинировать несколько условий для более точного выбора.

a[target='_blank']

Этот селектор выберет только те ссылки, которые открываются в новой вкладке.

10

Universal Selector. Универсальный селектор(*)
Он применяет стили ко всему, что есть в HTML-документе.

div > *

Этот локатор выберет все дочерние элементы внутри <div>.

11

Adjacent Sibling Selector. Селектор по соседнему элементу (+)

h2 + p

Выбирает элемент <p>, что находится непосредственно после элемента <h2>.

12

Селектор по следующим элементам (~)
(General Sibling Selector).

h2 ~ p

Выбирает все элементы <p>, что находятся  после элемента <h2>.

13

Negation Selector.
Селектор отрицания (:not)
Исключает элементы, которые соответствуют указанному селектору.

div:not(.hidden)

Выберет все <div>, у которых нет класса hidden.

14

Начинается с - (^=)
Выбирает элементы, у которых значение атрибута начинается с указанной строки.

[class^='btn-']

Выберет все элементы, у которых класс начинается с btn- (например, btn-primary, btn-secondary).

15

Заканчивается на - ($=)
Выбирает элементы, у которых значение атрибута заканчивается указанной строкой.

[src$='.jpg']

Выберет все элементы, у которых атрибут src 
заканчивается на .jpg.

16

Содержит - (*=)
Выбирает элементы, у которых значение атрибута содержит указанную строку.

[class*='menu']

Выберет все элементы, у которых класс содержит menu 
(например, main-menu, sidebar-menu).

17

Начинается с или равно (|=) Выбирает элементы, у которых значение атрибута начинается с указанной строки или равно ей.

[lang|='en']

Выберет все элементы, у которых атрибут lang 
начинается с en или равен en 
(например, en, en-US, en-GB).

Селекторы CSS не универсальны: они не могут однозначно идентифицировать любой элемент на странице и не умеют выбирать элементы по текстовому содержимому, и не всегда могут выбирать элементы по индексу. Для таких локаторов нам понадобится XPath.

Родственные связи элементов в DOM

Все начинается с корневого элемента. Корневой элемент (Root) — это самый верхний элемент в DOM, обычно <html>.

При изучении локаторов в контексте HTML и автоматизированного тестирования важно понимать иерархию и отношения между элементами в DOM. Это поможет вам верно находить элементы и писать стабильные локаторы.

1. Дети (Children)

Дети — это элементы, которые находятся внутри другого элемента (родителя).

<div id="parent">
  <span>Child 1</span>
  <span>Child 2</span>
</div>

 // Здесь <span> элементы — дети <div>

2. Родители (Parents)

Родитель — это элемент, который содержит другой элемент. В примере выше
<div> — родитель для <span>. В CSS нет прямого селектора для выбора родителя, он не поддерживает выбор родителя.

3. Предки (Ancestors)

Предки — это все элементы, которые находятся выше в иерархии DOM, включая родителей, их родителей и так далее.

<div id="grandparent">
  <div id="parent">
    <span>Child</span>
  </div>
</div>

// Здесь <div id="grandparent"> и <div id="parent"> — предки <span>.

4. Потомки (Descendants)

Потомки — это все элементы, которые находятся внутри другого элемента, включая детей, их детей и так далее. В примере выше <span> и <div id="parent"> — потомки <div id="grandparent">.

5. Соседи (Siblings)

Соседи — это элементы, которые находятся на одном уровне иерархии и имеют общего родителя.

<div>
  <span>Sibling 1</span>
  <span>Sibling 2</span>
</div>

// Здесь два <span> — соседи.

Локаторы основанные на XPath

XPath (XML Path Language) — язык запросов для поиска элементов в XML и HTML. Он использует путь (path) для навигации по элементам в документе. Абсолютный XPath начинается с корневого элемента (обычно /html) и описывает полный путь до нужного элемента. Относительный XPath начинается с текущего контекста (обычно //) и ищет элемент в любом месте документа.

nth — это сокращение от "n-th" (n-ный), которое используется в CSS и XPath для выбора элементов по их порядковому номеру в группе, для работы с элементами, которые имеют одинаковые теги или классы, но вам нужно выбрать конкретный элемент по его позиции.

Главное отличие от CSS‑селекторов в контексте локаторов в том, что XPath позволяет выбирать элементы напрямую, где: li[2] указывает на второй <li> среди всех, тогда как в CSS приходится писать nth-child(2). Кроме того, CSS‑селекторы работают только внутри родителя, не поддерживают абсолютный порядок на странице и не умеют использовать отрицательные индексы, а XPath позволяет выбирать элементы по абсолютному порядку, включая выбор с конца с помощью last(). Например, //ul/li[last()-1] выберет второй элемент с конца.

На примере списка:

<ul>
  <li>Первый</li>
  <li>Второй</li>
</ul>
<ul>
  <li>Третий</li>
  <li>Четвертый</li>
</ul>

CSS селектор li:nth-child(2) выберет «Второй» в первом <ul> и «Четвертый» во втором <ul>, так как nth-child работает в пределах каждого родителя <ul>.

XPath //li[2] выберет только «Второй», потому что он считает элементы по всему документу, а не внутри отдельных <ul>.

Еще одно преимущество XPath — возможность искать элементы по тексту, что часто привлекает новичков. Например, //button[text()='Отправить'] находит кнопку с нужным текстом, тогда как CSS такой возможности не дает. Однако привязка к тексту ненадежна: локализация, динамическое изменение контента или скрытые пробелы могут сделать такой селектор нестабильным.

Основные символы в XPath

Символ

Пример

Описание

1

//Поиск в любом месте документа.

Ищет элементы в любом месте документа, на любом уровне вложенности.

//div

Найдет все элементы <div> на странице, независимо от их расположения.

2

/ Поиск от корня или переход на уровень ниже.

- Есла прописан в начале (/html), начинает поиск от корневого элемента.
- Когда стоит между элементами (div/span), переходит на уровень ниже.

/html/body/div

Найдет элемент <div>, который является прямым потомком <body>, который, в свою очередь, является прямым потомком <html>.

3

[] Квадратные скобки (предикаты). Используется для указания условий фильтрации элементов.

//div[@class='container']

Найдет все элементы <div>, у которых атрибут class равен container.

4

@ Собачка (атрибуты). Указывает, что мы работаем с атрибутом элемента.

//input[@type='submit']

Найдет все элементы <input>, у которых атрибут type равен submit.

5

* Звездочка (любой элемент). Заменяет любой тег.

//*[@class='button']

Найдет все элементы (независимо от тега), у которых атрибут class равен button.

6

. Точка (текущий элемент). Обозначает текущий элемент (контекст).

.//span

Найдет все элементы <span>, которые являются потомками текущего элемента.

7

.. Двойная точка (родительский элемент). Переходит к родительскому элементу.

//input[@type='text']/..

Найдет родительский элемент для <input> с type="text".

8

text() — Функция для работы с текстом. Позволяет искать элементы по тексту.

//button[text()='Submit']

Найдет все элементы <button> с текстом "Submit".

9

contains() — Функция для частичного совпадения. Позволяет искать элементы, у которых атрибут или текст содержит указанную строку.

//div[contains(@class, 'menu')]

Найдет все элементы <div>, у которых атрибут class содержит menu.

10

andor — Логические операторы. Позволяют комбинировать условия.

//input@type='text' and @name='username']

Найдет все элементы <input>, у которых type="text" и name="username".

Примеры XPath-селекторов

Формально, XPath использует выражения (expressions), а не селекторы, как CSS. Но в разговорной и технической среде «XPath‑селекторы» тоже встречается, особенно в контексте тестирования. Здесь простые селекторы тоже выбирают элементы на основе тега элемента, идентификатора и класса, но записываются по‑другому. Ниже еще приведу примеры XPath, включая основные символы и конструкции выражений. По‑прежнему важно обращать внимание на знаки, символы и их роль в синтаксисе.

XPath-селектор
XPath-селектор

Конструкция

Пример

Описание

1

Выбор элемента
по тегу

//div

Выберет все элементы <div> на странице.

2

Выбор элемента
по атрибуту

//input[@type='submit']

Выберет все элементы <input> с атрибутом type=«submit».

3

Выбор элемента
по тексту

//button[text()='Submit']

Выберет все элементы <button> с текстом «Submit».

4

Выбор элемента по частичному совпадению текста

//button[contains(text(), 'Sub')]

Выберет все элементы <button>, текст которых содержит «Sub».

5

Выбор элемента по нескольким условиям

//input[@type='text' and @name='username']

Выберет все элементы <input>, у которых type=«text» и name=«username».

6

Выбор элемента
по позиции

(//div@class='item'])[2]

Выберет второй элемент <div> с классом item.

7

Выбор элемента по вложенности

//div@class='container']//input

Выберет все элементы <input>, которые находятся внутри <div> с классом container.

8

Выбор элемента по дочернему элементу

//ul/li

Выберет все элементы <li>, которые являются прямыми детьми <ul>.

9

Выбор элемента по атрибуту с частичным совпадением

//div[contains@class, 'menu')]

Выберет все элементы <div>, у которых класс содержит menu.

10

Выбор элемента по родителю

//input@type='text']/parent::div

Выберет элемент <div>, который является родителем <input> с type=«text».

XPath позволяет использовать абсолютные пути, что начинаются с корня, например, /html/body/div, но они хрупкие и ломаются при изменении структуры страницы. Лучше использовать относительные пути — начинаются с //, ищут элементы в любом месте документа и более устойчивы к изменениям.

Еще один плюс XPath, что поддерживает поиск по тегам, атрибутам, тексту и сложным условиям (например, contains() или and/or), но важно избегать излишне сложных запросов, так как они могут быть медленными и трудными для поддержки. В целом, XPath — это гибкий инструмент, но его стоит применять с умом. Не рекомендую им злоупотреблять и если можно использовать CSS‑селекторы, лучше использовать их, так как они проще и быстрее.

Локаторы в Playwright и Cypress

Playwright поддерживает как CSS так и XPath напрямую, можно искать элементы по тексту, структуре и сложным правилам, и есть еще собственные нативные локаторы, например, getByRole(), getByText(), getByTestId(), которые упрощают работу с элементами, но под капотом они всё равно используют CSS и XPath.

await page.locator("//button[text()='Submit']").click();

Cypress поддерживает только CSS‑селекторы, но при необходимости можно подключить поддержку XPath через плагин.

//Установить пакет:
npm install -D cypress-xpath
 // Затем подключить в cypress/support/e2e.js:
import 'cypress-xpath';

Теперь можно писать:

cy.xpath("//button[text()='Submit']").click();

Cypress рекомендует по возможности использовать все-таки CSS‑селекторы и предлагает некоторые следующие решения для замены XPath:

cy.get('[data-test="submit-button"]') //лучший вариант (через data-* атрибут).
cy.contains('Submit') // если нужно найти элемент по тексту.
cy.get('button').contains('Submit') // если нужен <button> с текстом "Submit".

При выборе локаторов важно учитывать возможности фреймворка, чтобы тесты оставались стабильными и удобными в поддержке.

Оптимальная стратегия выбора локаторов

Выбор локаторов зависит от контекста, структуры проекта и требований к тестам. Автоматизация тестирования WEB требует учитывать динамическую природу UI, скорость тестов и устойчивость локаторов. Вот базовые рекомендации:

  1. Приоритетность. Используйте самый простой, стабильный и быстрый вариант, комбинируя методы при необходимости. В приоритете тестовые атрибуты и id. Если их нет — class + уточняющий контекст. В крайнем случае — XPath по тексту, но с осторожностью: в многоязычных приложениях и в интерфейсах с переводом текст меняется и локатор ломается. В общем и целом меньше всего рекомендую цепляться за текст.

  2. Уникальность и валидность локаторов. Локатор должен уникально идентифицировать элемент. При необходимости комбинируйте атрибуты, например:

    div.button[name='submit'];

    Проверяйте локаторы в DevTools перед использованием в коде. Убедитесь, что локаторы работают в разных браузерах и разрешениях экрана.

  3. Читабельность и поддержка. Локаторы должны быть понятны разработчикам и тестировщикам.

  4. Стабильность локаторов. Избегайте слишком сложных XPath или CSS-селекторов, они могут сломаться при малейших изменениях в HTML. Избегайте слишком длинных выражений и вложенные XPath.

  5. Производительность. CSS-селекторы работают быстрее, чем XPath. Минимизируйте использование XPath.

  6. Адаптация к изменениям. Используйте относительные пути, чтобы локаторы были менее чувствительны к изменениям в HTML.

  7. Локаторы для динамических элементов. Для поиска элементов с динамическими классами используйте частичные совпадения:

    //xpath
    div[contains(@class, 'dynamic-class')];
    //css
    div[class*='dynamic-class'];

Надеюсь, это статья останется не просто справочником, каких много, а помогла вам понять тему. Для лучшего результата, рекомендую провести время за обучением в игровой форме на тренажере по ссылке https://flukeout.github.io

Успехов нам в автоматизации тестирования!

Теги:
Хабы:
Всего голосов 5: ↑5 и ↓0+6
Комментарии2

Публикации

Истории

Работа

Ближайшие события

19 марта – 28 апреля
Экспедиция «Рэйдикс»
Нижний НовгородЕкатеринбургНовосибирскВладивостокИжевскКазаньТюменьУфаИркутскЧелябинскСамараХабаровскКрасноярскОмск
22 апреля
VK Видео Meetup 2025
МоскваОнлайн
23 апреля
Meetup DevOps 43Tech
Санкт-ПетербургОнлайн
24 апреля
VK Go Meetup 2025
Санкт-ПетербургОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань
20 – 22 июня
Летняя айти-тусовка Summer Merge
Ульяновская область