1. Основы CSS-селекторов: выбор элементов по типу тега и уникальному идентификатору ID
Основы CSS-селекторов: выбор элементов по типу тега и уникальному идентификатору ID
Представьте, что вы стоите перед огромным складским стеллажом, где лежат тысячи коробок. Ваша задача — найти одну конкретную деталь для сборки механизма. Если вы скажете помощнику: «Принеси мне синюю коробку», он может вернуться с десятком разных вариантов. Если вы скажете: «Принеси коробку с артикулом AX-505», он доставит именно то, что нужно. В мире веб-разработки и автоматизации тестирования ситуация идентична: браузер — это огромный склад элементов (DOM-дерево), а CSS-селекторы — это те самые команды, которые позволяют нам безошибочно указывать на нужные объекты.
Для автоматизатора выбор правильного «пути» к элементу — это вопрос не только скорости, но и стабильности теста. Плохой локатор сломается при малейшем изменении дизайна, хороший — переживет рефакторинг кода. Начнем с фундамента: выбора элементов по их «биологическому виду» (тегу) и «личному номеру» (ID).
Анатомия веб-страницы через призму локаторов
Прежде чем писать первый селектор, необходимо понять, на что мы смотрим. Веб-страница — это иерархическая структура, известная как DOM (Document Object Model). Каждый элемент в этой структуре имеет имя (тег), набор атрибутов (свойства) и текстовое содержимое.
Когда мы пишем CSS-правила, браузер использует селекторы, чтобы понять, к каким узлам применить стили. Когда мы пишем автотесты на Selenium, Playwright или Cypress, мы используем те же самые селекторы, чтобы сказать инструменту: «Кликни вот сюда».
Селектор типа (Type Selector)
Самый простой и очевидный способ найти элемент — обратиться к нему по имени тега. Если нам нужны все заголовки первого уровня, мы пишем h1. Если нам нужны все кнопки — button.
Синтаксис селектора типа максимально лаконичен: это просто имя тега без каких-либо дополнительных символов.
В контексте тренажера CSS Diner, который имитирует обеденный стол с посудой, селектор типа работает так: если на столе стоят тарелки (<plate />) и яблоки (<apple />), то селектор plate выберет все тарелки, независимо от того, что на них лежит или какого они цвета.
Нюансы использования селекторов типа в тестах:
div или 20 элементов a (ссылок). Использование голого селектора типа в 99% случаев приведет к тому, что ваш автотест найдет «первый попавшийся» элемент или выдаст ошибку о не уникальности локатора.nav или footer, хотя и это не всегда так).span на div для улучшения блочной модели, ваш локатор span мгновенно перестанет работать, хотя визуально для пользователя ничего не изменится.Магия уникальности: Селектор ID
Если тег — это фамилия (очень распространенная, как «Иванов»), то ID — это номер паспорта. Согласно спецификации HTML, идентификатор (id) должен быть уникальным в пределах всей страницы. Это делает его «золотым стандартом» для автоматизации.
Синтаксис селектора по ID в CSS обозначается символом решетки #.
В коде страницы это выглядит так:
<orange id="fancy" />
Почему ID так важен для тестировщика? Представьте форму регистрации. На ней может быть пять текстовых полей (input). Если вы используете селектор input, тест запутается. Но если у поля «Имя пользователя» есть id="username", а у поля «Пароль» — id="password", вы получаете прямой и быстрый доступ к цели.
Почему ID может подвести?
Несмотря на кажущуюся идеальность, у идентификаторов есть свои «подводные камни»:
* Динамические ID. Многие современные фреймворки (React, Angular, Vue) при использовании определенных библиотек компонентов генерируют ID автоматически. Если вы видите локатор вида #j_id_jsp_12345_6, скорее всего, при следующей перезагрузке страницы цифры изменятся. Использовать такие ID в тестах категорически нельзя — это путь к «хрупким» тестам, которые падают без видимых причин.
* Дублирование ID. К сожалению, браузеры прощают ошибки разработчиков. Если на странице окажется два элемента с id="submit", страница все равно отобразится. Однако CSS-селектор применится к обоим, а метод поиска элемента в автотестах (например, findElement) вернет только первый. Это может создать ложное ощущение стабильности, пока порядок элементов не изменится.
* Отсутствие ID. В идеальном мире разработчики расставляют id для всех ключевых элементов (это называется «тестопригодностью» или testability). В реальности же ID часто отсутствуют, и тестировщику приходится выстраивать сложные цепочки из других селекторов.
Практический разбор на примере CSS Diner
Рассмотрим уровни тренажера, чтобы закрепить базу.
Кейс 1: Выбор по тегу
На столе стоят две тарелки. В HTML это выглядит так:Чтобы выбрать их обе, нам достаточно написать селектор plate. Это самый базовый уровень абстракции. Мы не смотрим на содержимое, нам важен тип объекта.
Кейс 2: Выбор по ID
На столе стоит обычная тарелка и тарелка с идентификаторомfancy:Если мы напишем plate, мы выберем обе. Но если задача — выбрать только «модную» тарелку, наш выбор — #fancy. Обратите внимание: мы могли бы написать plate#fancy (сочетание тега и ID), но это избыточно. Поскольку ID уникален, #fancy и так найдет нужный объект быстрее и лаконичнее.
Комбинирование селекторов: когда типа и ID мало
Иногда нам нужно уточнить запрос. Хотя ID уникален сам по себе, в сложных системах или при изучении чужого кода вы можете встретить конструкцию tag#id.
Например: div#main-container.
Зачем это нужно, если #main-container и так сработает?
div. Если разработчик изменит его на section, локатор перестанет работать, что может быть полезно для проверки строгого соответствия верстки спецификации.Однако в автоматизации действует правило: чем короче и проще локатор, тем он лучше. Избыточность — враг поддержки. Если #login-button работает, не пишите button#login-button.
Сравнение: Тег против ID
Для наглядности сопоставим эти два фундаментальных способа поиска в таблице:
| Характеристика | Селектор типа (tag) | Селектор ID (#id) |
| :--- | :--- | :--- |
| Синтаксис | div, p, button | #my-element, #header |
| Уникальность | Низкая (много элементов на странице) | Высокая (один элемент на странице) |
| Стабильность | Средняя (зависит от структуры тегов) | Высокая (если ID не динамический) |
| Скорость поиска | Высокая (нативный поиск браузера) | Максимальная (индексируется браузером) |
| Применение | Групповые операции, простые страницы | Точечное взаимодействие с элементами |
Приоритетность и специфичность (краткий экскурс)
В CSS существует понятие «специфичности» (вес селектора). Хотя для поиска элементов в автотестах это не так критично, как для стилизации, понимание веса помогает разобраться, почему один селектор «сильнее» другого.
Математически это можно представить так: * Селектор типа дает 1 балл. * Селектор ID дает 100 баллов.
Если у вас есть элемент <button id="send-mail" />, то селектор #send-mail будет гораздо более специфичным и точным, чем просто button. Для инструментов автоматизации это означает, что поиск по ID — это самый «быстрый» путь, так как браузеры создают внутренние хэш-таблицы для всех ID на странице, что позволяет находить их практически мгновенно, не перебирая всё дерево DOM.
Граничные случаи и ошибки новичков
Ошибка 1: Использование ID с символом решетки в атрибутах
Новички часто путают значение атрибута и синтаксис селектора. В HTML мы пишем:id="user-name".
В CSS мы пишем: #user-name.
Нельзя писать в коде теста локатор id="#user-name", если метод уже подразумевает использование CSS-селектора. Решетка — это указатель типа «ищи по идентификатору».Ошибка 2: Попытка найти элемент по ID, которого нет в DOM
Часто в динамических приложениях элемент появляется не сразу. Если вы ищете#success-message сразу после клика на кнопку, тест может упасть, потому что скрипт еще не успел отрисовать этот блок. Всегда помните: наличие уникального ID не отменяет необходимости ожиданий (waits) в автотестах.Ошибка 3: Игнорирование регистра
Хотя теги в HTML обычно нечувствительны к регистру (DIV и div — это одно и то же), ID в некоторых браузерах и стандартах могут быть чувствительны. Хорошим тоном считается писать всё в нижнем регистре или в стиле kebab-case (через дефис), как это принято в современной веб-разработке.Почему мы начинаем именно с этого?
Выбор по тегу и ID — это фундамент. Это как умение читать буквы перед тем, как писать романы. В следующих темах мы разберем классы, которые позволяют группировать элементы, и иерархические связи, позволяющие перемещаться между «родителями» и «детьми». Но даже в самых сложных проектах по автоматизации, если у элемента есть вменяемый, статичный ID — опытный тестировщик всегда выберет именно его.
Умение вовремя остановиться и не усложнять локатор — признак мастерства. Если задача решается простым #submit, не нужно строить конструкцию из пяти вложенных тегов. Простота — залог того, что через полгода, когда вы вернетесь к своим тестам, вы поймете, что они делают, а не будете разгадывать ребусы из CSS-символов.
На этапе обучения в CSS Diner старайтесь замечать, как меняется поведение элементов при наведении: тег выбирает «все похожие», а ID — «тот самый единственный». Это различие должно закрепиться на уровне интуиции.