Какой бы инструмент вы ни выбрали для автоматизации тестирования, все они будут искать элементы с помощью локаторов, и обычно это означает, что вы, как тестировщик, должны их создавать используя селекторы. Какие бывают локаторы, как они выглядят, чем отличаются, какие лучше использовать, а какие избегать и почему, ответы прочтете здесь.
Примеры скриптов покажу на 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).
Открыть вкладку 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
<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. | #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. Селектор по псевдоэлементу (::) | p::first-line | Выберет первую строку текста в параграфе. |
8 | Child Selector. | ul > li | Этот селектор выберет только те <li>, которые являются прямыми детьми <ul>. |
9 | Селектор по нескольким условиям. Можно комбинировать несколько условий для более точного выбора. | a[target='_blank'] | Этот селектор выберет только те ссылки, которые открываются в новой вкладке. |
10 | Universal Selector. Универсальный селектор(*) | div > * | Этот локатор выберет все дочерние элементы внутри <div>. |
11 | Adjacent Sibling Selector. Селектор по соседнему элементу (+) | h2 + p | Выбирает элемент <p>, что находится непосредственно после элемента <h2>. |
12 | Селектор по следующим элементам (~) | h2 ~ p | Выбирает все элементы <p>, что находятся после элемента <h2>. |
13 | Negation Selector. | div:not(.hidden) | Выберет все <div>, у которых нет класса 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>.
При изучении локаторов в контексте 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> на странице, независимо от их расположения. |
2 |
- Есла прописан в начале (/html), начинает поиск от корневого элемента. |
| Найдет элемент <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 |
| //button[text()='Submit'] | Найдет все элементы <button> с текстом "Submit". |
9 |
| //div[contains(@class, 'menu')] | Найдет все элементы <div>, у которых атрибут class содержит menu. |
10 |
| Найдет все элементы <input>, у которых type="text" и name="username". |
Примеры XPath-селекторов
Формально, XPath использует выражения (expressions), а не селекторы, как CSS. Но в разговорной и технической среде «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» и 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, скорость тестов и устойчивость локаторов. Вот базовые рекомендации:
Приоритетность. Используйте самый простой, стабильный и быстрый вариант, комбинируя методы при необходимости. В приоритете тестовые атрибуты и
id
. Если их нет —class
+ уточняющий контекст. В крайнем случае — XPath по тексту, но с осторожностью: в многоязычных приложениях и в интерфейсах с переводом текст меняется и локатор ломается. В общем и целом меньше всего рекомендую цепляться за текст.Уникальность и валидность локаторов. Локатор должен уникально идентифицировать элемент. При необходимости комбинируйте атрибуты, например:
div.button[name='submit'];
Проверяйте локаторы в DevTools перед использованием в коде. Убедитесь, что локаторы работают в разных браузерах и разрешениях экрана.
Читабельность и поддержка. Локаторы должны быть понятны разработчикам и тестировщикам.
Стабильность локаторов. Избегайте слишком сложных XPath или CSS-селекторов, они могут сломаться при малейших изменениях в HTML. Избегайте слишком длинных выражений и вложенные XPath.
Производительность. CSS-селекторы работают быстрее, чем XPath. Минимизируйте использование XPath.
Адаптация к изменениям. Используйте относительные пути, чтобы локаторы были менее чувствительны к изменениям в HTML.
Локаторы для динамических элементов. Для поиска элементов с динамическими классами используйте частичные совпадения:
//xpath div[contains(@class, 'dynamic-class')];
//css div[class*='dynamic-class'];
Надеюсь, это статья останется не просто справочником, каких много, а помогла вам понять тему. Для лучшего результата, рекомендую провести время за обучением в игровой форме на тренажере по ссылке https://flukeout.github.io
Успехов нам в автоматизации тестирования!