January 31, 2020

Краткий ликбез по локаторам в вебе

"Любишь UI-автотесты писать, люби и локаторы подбирать" (с) Конфуций

Конфуций, конечно, был мудрым человеком, и ещё поговаривал, что знание локаторов пригождется не только тем, кто работает с автоматизацией клиентской части.

Зачем это мне?

🔹 Если вы можете быстро найти локатор элемента, то репортить баги UI-части становится в разы проще. Вместо того, чтобы искать "красную нопку ОК на странице авторизации пользователя в личный кабинет", разработчик вбивает в поиск ".btn.submit" и моментально находит элемент, для которого нужно сделать исправления.

🔹 Если вы знаете, как работают CSS-селекторы, то можете проверять работу визуальной части не только как пользователь, но и как... скажем, продвинутый пользователь. Например, обнаружить, что выполненный пункт в ToDo-листе не перечеркивается, потому что не подтянулся стиль, который отвечает за то, чтобы текст элемента, находящегося в определенном состоянии, был зачеркнут.

🔹 Вообще механика работы веба — того, что мы, собственно, тестируем — становится намного понятнее, а работать с тем, что понимаешь, в разы приятнее. Кроме того, появляются новые идеи для проверок: а что будет, если мы уберем вот этот атрибут и попробуем ввести в поле невалидное значение? А если у кнопки стереть 'disabled' и кликнуть на неё, что-то произойдет?

🔹 Можно открывать новые для себя направления деятельности: например, одна моя коллега не пишет UI-тесты, но редактирует код страниц и добавляет элементам data-test-* атрибуты. Это требует аналитического мышления, системного подхода и внимательности, а ещё позволяет порботать с кодом, но без написания автотестов (если вдруг вам их писать не очень хочется).

Короче, локаторы нужны и важны, а DevTools (F12 в большинстве браузеров) — наш лучший друг.

Что такое локаторы?

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

То есть если обычно вы видите кнопку "Login" и знаете, что надо нажать именно на неё, то в случае с автоматизацией браузеру надо дать команду "нажать", а ещё обозначить, что именно жать. Собственно, чтобы взаимодействие браузера происходило с нужным вам элементом, а не соседним или вообще скрытым, и нужно умение писать уникальные локаторы. Ещё хорошо, чтобы локаторы были читабельными — тогда вашим коллегам будет проще понимать, к чему именно вы обращаетесь (и что пошло не так в случае проблемы), но это уже, увы, не всегда зависит от QA.

Какие виды локаторов существуют?

Selenium WebDriver ищет элементы с помощью двух методов:

  • Find Element
  • Find Elements

Оба получают на вход параметры: объект класса By + тип запроса (по чему будем искать элемент) и сам локатор. Локатор должен соответствовать типу запроса: если ищем по атрибуту, то в локатор кидаем значение атрибута, если по СSS-селектору — то селектор. Если запрос будет вида

find_element(By.XPATH, "#login_form")

, то, разумеется, вместо рабочего теста мы получим ошибку.

Пара других различий, которые важно знать о методах Find Element и Find Elements:

Различия методов Find Element и Find Elements

Объект класса By может принимать на вход следующие виды локаторов:

  • ID
  • Name
  • XPath
  • Link text
  • Partial link text
  • Tag name
  • Class name
  • CSS selector

При этом ID, Name, Tag name и Class name — частные случаи CSS-селекторов. Таким образом, основные виды локаторов, с которыми мы будем сталкиваться — это CSS-селекторы и XPath. О них и поговорим ниже.

CSS Selector

Использует для поиска элемента его части (атрибуты). Изначальная цель использования —поиск элементов HTML-странички и навешивание на них стилей. Так как стилями нужно мочь обвешать все элементы страницы, синтаксис селекторов разработан с ориентиром на максимальную гибкость.

Синтаксис:

  • id (#uniqueid)
  • tag (H1)
  • name ([name="my-element"])
  • class (.class1.class2)
  • другое значение атрибута ([attribute="value"])
  • текст в элементе: псевдокласс из jquery :contains()
  • положение потомка: :nth-child(1)

Примеры использования:

  • #test — поиск по ID “test”
  • tag — поиск по тэгу “tag”
  • .my-class — поиск по классу “my-class”
  • .class1.class2 — поиск по классам “class1 class2” или “class2 class1” (обратите внимание, что порядок классов элемента не имеет значения при написании селектора)
  • [name="my-name"] — поиск по имени "my-name"
  • [attribute="value"] — поиск по значению "value" атрибута “attribute”
  • a:contains("test") — поиск по тексту "test", который содержится в элементе
  • #posts > .item:nth-child(2) > .title — составной селектор. Ищет элемент с классом title, который является потомком второго потомка элемента с классом item, который, в свою очередь, потомок элемента с ID = posts

XPath

Поиск элемента(ов) с помощью запроса XPath (XML path) — языка разметки в XML-документе. Приятный момент работы с XPath: здесь, в отличие от селекторов, можно производить перемещение как в глубину DOM-иерархии, так и в обратную сторону (например, искать родительский элемент по дочернему).

Синтаксис:

  • / — поиск прямого потомка
  • // — поиск потомка любой степени
  • [ ] — фильтрация
  • Функция text() - поиск по тексту элемента
  • Функция contains() - поиск полного или частичного совпадения
  • Булевы операции and, or, not
  • * - выбор всех элементов

Важный момент: XPath регистрозависим. То есть если запрос вида //*[@class=”my-class”] находит элемент, то запрос вида //*[@Сlass=”my-Сlass”] тот же элемент не обнаружит.

Возможный вид запроса:

//корень(конкретный или *)/потомок[параметры фильтрации]

Примеры использования:

  • //*[@class=”my-class”] — поиск по всем элементам, у которых есть класс ”my-class”
  • //div/p/a[text()=”Пример текста”] — поиск по всем элементам a, содержащим текст ”Пример текста” и являющимся прямыми потомками элемента p, который прямой потомок элемента div
  • //*[@data-test=”select-button” or contains(@class, “login-button”)] — поиск по всем элементам, у которых есть data-test-атрибут со значением ”select-button” ИЛИ у которых в имени класса есть “login-button”
  • //div[1] — выбор первого потомка элемента div

DevTools наш друг

Чтобы искать элементы быстрее и убедиться, что написанный запрос вернет нам нужное количество элементов страницы, можно (и нужно) использовать DevTools. Они открываются по нажатию F12 или комбинации Ctrl+Shift+I. Во вкладке Elements можно посмотреть код страницы и скопировать уникальный локатор того или иного элемента. Ещё пару лет назад таким образом возвращались трудночитабельные монстры, но браузеры умнеют (как и мы), и теперь часто Chrome возвращает отличные лаконичные локаторы.

Селекторы и локаторы можно искать и проверять через DevTools

Как же овладеть искусством поиска красивых локаторов? Практика, практика, практика!

Почитать (и потренироваться) дополнительно можно вот тут:

1. На официальном сайте Selenium: https://www.seleniumhq.org/docs/03_webdriver.jsp#locating-ui-elements-webelements

2. В документации к Selenium для вашего языка программирования. Вот так выглядит вариант для Python: https://selenium-python.readthedocs.io/locating-elements.html

3. В других местах:

4. А вот тут можно найти готовые подсказки по CSS-селекторам, XPath и многому другому интересному ;)

Если вы хотите лишний раз попрактиковаться в написании CSS-селекторов — часто используемых локаторов — рекомендуем вам заглянуть на https://www.w3schools.com/css/exercise.asp и https://flukeout.github.io/.

Тем, кому совсем интересно и хочется больше практики из реальной жизни, поможе вот такое нетрудное упражнение:

  1. Выбрать туториал с любой формой из раздела Forms W3Schools (например, первый — Login Form)
  2. На странице туториала кликнуть кнопку Try it yourself
  3. Скопировать код из левой части редактора и сохранить на вашем компьютере в формате HTML
  4. Открыть сохраненную HTML-страницу и поискать для каждого элемента разного рода атрибуты и тэги.

А ещё очень рекомендуем обратить внимание на шаги 1.4 - 1.6 курса Автоматизация тестирования с помощью Selenium и Python и на модули 5 и 6 курса Веб-разработка для начинающих: HTML и CSS.

Когда вы чувствуете, что готовы попробовать поиск и написание локаторов на реальном веб-сайте, вы можете использовать песочницы из предыдущего поста или что-то из списка ниже:

Надеюсь, этот ликбез оказался вам полезен! Всем интересных задач и красивых локаторов :)