Локаторы. Стратегии поиска веб-элементов
Какой бы инструмент вы ни выбрали для автоматизации тестирования, все они будут искать элементы с помощью локаторов, и обычно это означает, что вы, как тестировщик, должны их создавать используя селекторы. Какие бывают локаторы, как они выглядят, чем отличаются, какие лучше использовать, а какие избегать и почему, ответы прочтете здесь.
Примеры скриптов покажу на Playwright и Cypress.
Способы локаторов могут быть разными, но в сухом остатке есть только два типа —
CSS и XPath, их вариации и удобные сокращения. Все локаторы строятся на основе DOM и работают с селекторами для поиска элементов.
Элемент — это сам HTML‑объект на странице, например, кнопка «Отправить».
Селектор — это способ найти этот элемент в DOM, например:
#submit (по id),
btn (по классу),
'button' (по тегу).
Локатор использует этот селектор, например:
await page.locator('#submit').click(); // Playwright
cy.get('#submit').click(); // CypressБазовые локаторы

Тестовые атрибуты отличаются от других локаторов тем, что они специально добавляются в код для тестирования и не зависят от изменений в верстке.
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).
Открыть вкладку Elements.
Скопировать id элемента в буфер.
Нажать Ctrl + F (Cmd + F на macOS) для поиска.
Ввести
id="your‑id"(замените your‑id на нужный).
Если результат 1 то все хорошо.
Если > 1, значит id повторяется, это баг.
В общем и целом, советую так же проверять любой селектор, чтобы убедиться, что он точно указывает на нужный элемент, является уникальным и стабильным. Проверка стабильности локатора в DevTools — это про то, чтобы убедиться, что он не изменится например, при перезагрузке страницы и переключении языковой версии сайта. Популярные проверки, остается ли селектор валидным:
Перезагрузить страницу (F5).
Убедиться, что селектор не содержит динамических атрибутов.
Проверить, меняется ли локатор при разных действиях (например, переключение вкладок, прокрутка, изменение состояния).
Попробовать открыть сайт в анонимном режиме или другом браузере.
Изменить размер экрана (Ctrl + Shift + M в DevTools, эмулировать мобильное устройство).
Переключить язык, если сайт поддерживает мультиязычность, и убедиться, что локатор остается рабочим.
Атрибуты name — еще один хороший локатор.
Атрибут name используется в элементах ввода (input, text‑area, select, button) для передачи данных на сервер. Каждый input в форме должен иметь уникальное значение name.
// HTML
// Playwright
await page.locator('[name="firstName"]').fill('firstNameTest');
await page.locator('[name="lastName"]').fill('lastNameTest');Он также группирует radio и checkbox: у radio, name должен быть одинаковым и выбирается один вариант, а у checkbox — тоже одинаковым, но можно выбрать несколько.
Чтение
Спорт
//Сервер получит hobby=reading&hobby=sports, если выбраны оба.CSS class name — это третий базовый локатор.
Имена классов определяют стиль CSS для HTML‑элементов. Однако, они также могут служить идентификаторами. Классы в HTML начинаются с точки (.)
У элемента может быть одно имя класса, несколько имён классов или не быть ни одного.
Тут несколько классовКроме того, имена классов не обязательно должны быть уникальными для каждого элемента. Одно имя класса может использоваться несколькими элементами. Это полезно при поиске набора элементов, например списка результатов поиска.
// 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 | Выберет все кнопки на странице с тегом |
2 | ID Selector. | #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, что находятся внутри . |
6 | Pseudo-classes. | button: hover | Выберет кнопку, когда на нее наведен курсор. |
7 | Pseudo-elements. Селектор по псевдоэлементу (:: ) | p:: first-line | Выберет первую строку текста в параграфе. |
8 | Child Selector. | ul > li | Этот селектор выберет только те
|
9 | Селектор по нескольким условиям. Можно комбинировать несколько условий для более точного выбора. | a[target='_blank'] | Этот селектор выберет только те ссылки, которые открываются в новой вкладке. |
10 | Universal Selector. Универсальный селектор (*) | div > * | Этот локатор выберет все дочерние элементы внутри . |
11 | Adjacent Sibling Selector. Селектор по соседнему элементу (+) | h2 + p | Выбирает элемент , что находится непосредственно после элемента . |
12 | Селектор по следующим элементам (~) | h2 ~ p | Выбирает все элементы , что находятся после элемента . |
13 | Negation Selector. | div: not(.hidden) | Выберет все , у которых нет класса hidden. |
14 | Начинается с — (^=) | [class^='btn-'] | Выберет все элементы, у которых класс начинается с btn- (например, btn-primary, btn-secondary). |
15 | Заканчивается на — ($=) | [src$='.jpg'] | Выберет все элементы, у которых атрибут src |
16 | Содержит — (*=) | [class*='menu'] | Выберет все элементы, у которых класс содержит menu |
17 | Начинается с или равно (|=) Выбирает элементы, у которых значение атрибута начинается с указанной строки или равно ей. | [lang|='en'] | Выберет все элементы, у которых атрибут lang |
Селекторы CSS не универсальны: они не могут однозначно идентифицировать любой элемент на странице и не умеют выбирать элементы по текстовому содержимому, и не всегда могут выбирать элементы по индексу. Для таких локаторов нам понадобится XPath.
Родственные связи элементов в DOM
Все начинается с корневого элемента. Корневой элемент (Root) — это самый верхний элемент в DOM, обычно .
При изучении локаторов в контексте HTML и автоматизированного тестирования важно понимать иерархию и отношения между элементами в DOM. Это поможет вам эффективно находить элементы и писать стабильные локаторы.
1. Дети (Children)
Дети — это элементы, которые находятся внутри другого элемента (родителя).
Child 1
Child 2
// Здесь элементы — дети 2. Родители (Parents)
Родитель — это элемент, который содержит другой элемент. В примере выше
— родитель для . В CSS нет прямого селектора для выбора родителя, он не поддерживает выбор родителя.3. Предки (Ancestors)
Предки — это все элементы, которые находятся выше в иерархии DOM, включая родителей, их родителей и так далее.
Child
// Здесь и — предки .4. Потомки (Descendants)
Потомки — это все элементы, которые находятся внутри другого элемента, включая детей, их детей и так далее. В примере выше и — потомки .5. Соседи (Siblings)
Соседи — это элементы, которые находятся на одном уровне иерархии и имеют общего родителя.
Sibling 1
Sibling 2
// Здесь два — соседи.
Локаторы основанные на XPath
XPath (XML Path Language) — язык запросов для поиска элементов в XML и HTML. Он использует путь (path) для навигации по элементам в документе. Абсолютный XPath начинается с корневого элемента (обычно /html) и описывает полный путь до нужного элемента. Относительный XPath начинается с текущего контекста (обычно //) и ищет элемент в любом месте документа.
nth — это сокращение от »n-th» (n-ный), которое используется в CSS и XPath для выбора элементов по их порядковому номеру в группе, для работы с элементами, которые имеют одинаковые теги или классы, но вам нужно выбрать конкретный элемент по его позиции.
Главное отличие от CSS‑селекторов в контексте локаторов в том, что XPath позволяет выбирать элементы напрямую, где: li[2] указывает на второй среди всех, тогда как в CSS приходится писать nth-child(2). Кроме того, CSS‑селекторы работают только внутри родителя, не поддерживают абсолютный порядок на странице и не умеют использовать отрицательные индексы, а XPath позволяет выбирать элементы по абсолютному порядку, включая выбор с конца с помощью last(). Например, //ul/li[last()-1] выберет второй элемент с конца.
На примере списка:
- Первый
- Второй
- Третий
- Четвертый
CSS селектор li:nth-child(2) выберет «Второй» в первом
и «Четвертый» во втором
, так как nth-child работает в пределах каждого родителя
.
XPath //li[2] выберет только «Второй», потому что он считает элементы по всему документу, а не внутри отдельных
.
Еще одно преимущество XPath — возможность искать элементы по тексту, что часто привлекает новичков. Например, //button[text()='Отправить'] находит кнопку с нужным текстом, тогда как CSS такой возможности не дает. Однако привязка к тексту ненадежна: локализация, динамическое изменение контента или скрытые пробелы могут сделать такой селектор нестабильным. В общем и целом меньше всего рекомендую цепляться за текст.
Основные символы в XPath
№
Символ
Пример
Описание
1
//Поиск в любом месте документа.
Ищет элементы в любом месте документа, на любом уровне вложенности.
//div
Найдет все элементы
на странице, независимо от их расположения.2
/ Поиск от корня или переход на уровень ниже.
- Есла прописан в начале (/html), начинает поиск от корневого элемента.
- Когда стоит между элементами (div/span), переходит на уровень ниже.
/html/body/div
Найдет элемент
, который является прямым потомком , который, в свою очередь, является прямым потомком .3
[] Квадратные скобки (предикаты). Используется для указания условий (фильтрации элементов).
//div[@class='container']
Найдет все элементы
, у которых атрибут class равен container.4
@ Собачка (атрибуты). Указывает, что мы работаем с атрибутом элемента.
//input[@type='submit']
Найдет все элементы , у которых атрибут type равен submit.
5
* Звездочка (любой элемент). Заменяет любой тег.
//*[@class='button']
Найдет все элементы (независимо от тега), у которых атрибут class равен button.
6
. Точка (текущий элемент). Обозначает текущий элемент (контекст).
.//span
Найдет все элементы , которые являются потомками текущего элемента.
7
.. Двойная точка (родительский элемент). Переходит к родительскому элементу.
//input[@type='text']/…
Найдет родительский элемент для с type=«text».
8
text() — Функция для работы с текстом. Позволяет искать элементы по тексту.
//button[text ()='Submit']
Найдет все элементы
9
contains() — Функция для частичного совпадения. Позволяет искать элементы, у которых атрибут или текст содержит указанную строку.
//div[contains (@class, 'menu')]
Найдет все элементы
, у которых атрибут class содержит menu.10
and, or — Логические операторы. Позволяют комбинировать условия.
//input@type='text' and @name='username']
Найдет все элементы , у которых type=«text» и name=«username».
Примеры XPath-селекторов
Формально, XPath использует выражения (expressions), а не селекторы, как CSS. Но в разговорной и технической среде «XPath‑селекторы» тоже встречается, особенно в контексте тестирования. Здесь простые селекторы тоже выбирают элементы на основе тега элемента, идентификатора и класса, но записываются по‑другому. В таблице приведены примеры XPath, включая основные символы и конструкции выражений. По-прежнему важно обращать внимание на знаки, символы и их роль в синтаксисе.
XPath-селектор№
Конструкция
Пример
Описание
1
Выбор элемента
по тегу
//div
Выберет все элементы
на странице.2
Выбор элемента
по атрибуту
//input[@type='submit']
Выберет все элементы с атрибутом type=«submit».
3
Выбор элемента
по тексту
//button[text ()='Submit']
Выберет все элементы
4
Выбор элемента по частичному совпадению текста
//button[contains (text (), 'Sub')]
Выберет все элементы
5
Выбор элемента по нескольким условиям
//input[@type='text' and @name='username']
Выберет все элементы , у которых type=«text» и name=«username».
6
Выбор элемента
по позиции
(//div@class='item'])[2]
Выберет второй элемент
с классом item.7
Выбор элемента по вложенности
//div@class='container']//input
Выберет все элементы , которые находятся внутри
с классом container.8
Выбор элемента по дочернему элементу
//ul/li
Выберет все элементы
, которые являются прямыми детьми .
9
Выбор элемента по атрибуту с частичным совпадением
//div[contains@class, 'menu')]
Выберет все элементы
, у которых класс содержит menu.10
Выбор элемента по родителю
//input@type='text']/parent: div
Выберет элемент
, который является родителем с type=«text».
XPathпозволяет использовать абсолютные пути (начинающиеся с корня, например, /html/body/div), но они хрупкие и ломаются при изменении структуры страницы. Лучше использовать относительные пути (начинающиеся с //), которые ищут элементы в любом месте документа и более устойчивы к изменениям.
Еще один плюс, что поддерживает поиск по тегам, атрибутам, тексту и сложным условиям (например, contains() или and/or), но важно избегать излишне сложных запросов, так как они могут быть медленными и трудными для поддержки. В целом, XPath — это гибкий инструмент, но его стоит применять с умом. Не рекомендую злоупотреблять сложными 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') // если нужен
При выборе локаторов важно учитывать возможности фреймворка, чтобы тесты оставались стабильными и удобными в поддержке.
Оптимальная стратегия выбора локаторов
Выбор локаторов зависит от контекста, структуры приложения и требований к тестам. Автоматизация тестирования WEB требует учитывать динамическую природу UI, скорость тестов и устойчивость локаторов. Вот базовые рекомендации:
Приоритетность. Используйте самый простой, стабильный и быстрый вариант, комбинируя методы при необходимости. В приоритете тестовые атрибуты и id. Если их нет — class + уточняющий контекст. В крайнем случае — XPath по тексту, но с осторожностью: в многоязычных приложениях и в интерфейсах с переводом текст меняется и локатор ломается. В общем и целом меньше всего рекомендую цепляться за текст.
Уникальность и валидность локаторов. Локатор должен уникально идентифицировать элемент. При необходимости комбинируйте атрибуты, например:
div.button[name='submit'];
Проверяйте локаторы в DevTools перед использованием в коде. Убедитесь, что локаторы работают в разных браузерах и разрешениях экрана.
Стабильность локаторов. Избегайте слишком сложных XPath или CSS-селекторов, они могут сломаться при малейших изменениях в HTML.
Производительность. CSS-селекторы работают быстрее, чем XPath. Минимизируйте использование XPath.
Читабельность и поддержка. Локаторы должны быть понятны разработчикам и тестировщикам.
Адаптация к изменениям. Используйте относительные пути, чтобы локаторы были менее чувствительны к изменениям в HTML. Избегайте слишком длинных выражений и вложенные XPath.
Локаторы для динамических элементов. Для поиска элементов с динамическими классами используйте частичные совпадения:
//xpath
div[contains(@class, 'dynamic-class')];
//css
div[class*='dynamic-class'];
Надеюсь, это статья останется не просто справочником, каких много, а помогла вам понять тему. Для лучшего результата, рекомендую провести время за обучением в игровой форме на тренажере по ссылке https://flukeout.github.io
Успехов нам в автоматизации тестирования!
Habrahabr.ru
прочитано 22146 раз
