Вот почему мы всегда пишем селекторы на XPath18.10.2021 13:32
Привет, Хабр! Сегодня хочется поговорить про XPath — мощный и гибкий инструмент для работы с веб-интерфейсами, который при этом почему-то остается не особенно популярным. Статей и мануалов по XPath очень много, и в этом посте я постараюсь рассказать, как мы применяем данный инструмент и почему считаем его более эффективным, чем другие подходы. Если вам знаком термин «селектор», а тем более — если вы слышали про XPath, добро пожаловать под кат, там много полезного!
В нашей команде работает целая группа инженеров-тестировщиков, которые ежедневно пишут автоматические end2end тесты для Selenium, а также создают огромное количество селекторов для них. С одной стороны, эта работа кажется несложной, но на практике к ней добавляются условия:
Писать код надо понятно и однотипно, потому что вы — не единственный инженер;
Всегда надо предусматривать возможность оперативно переписать селектор;
Для целого множества сайтов и версток необходимо обеспечить единый подход;
Важно гарантировать однозначность каждого селектора;
И, наконец, каждый селектор должен быть максимальную информативным.
С учетом всех этих требований, работа инженера-тестировщика становится не такой уж простой, потому что выполнять задачи необходимо с определенным уровнем унификации. И именно поэтому мы полностью отдали предпочтение XPath (XML Path Language) для написания селекторов.
Существует мнение (и оно довольно распространенное), что XPath это что-то громоздкое, со сложным синтаксисом. А некоторые также ставят под сомнение скорость поиска по XPath. Например, в одном из популярных курсов обучения по автоматизации тестирования с помощью Selenium, вы можете увидеть вот такие мысли:
Но наша практика показывает, что это не совсем так…а может быть даже совсем не так. Мы сделали ставку на XPath, потому что наша команда пишет автоматизированные тесты для заказчиков — фактически тысячи тестов. Чтобы увязать их с внедрением систем комплексного мониторинга, об этом я уже писал в прошлом посте. При таких объемах в условиях командной работы, стандартизация подходов является необходимостью, в том числе и для составления селекторов.
XPath: плюсы и минусы
Начнем с минусов — то есть с того, почему XPath не любят.
Минус №1. Холивары о скорости работы селекторов на XPath и, например, CSS действительно не затихают. Мы ввязываться в них не будем и не станем утверждать, что тот или иной подход работает быстрее. Но при этом стоит отметить, что, учитывая общее время выполнения UI теста, разница в скорости работы селектора вообще не существенна.
Минус №2. Многие считают селекторы XPath неинформативными. И это мнение обычно формируется после работы с плагинами для браузеров и стандартными средствами браузеров по поиску XPath. Действительно, селектор вида //div[1]/div[2]/ul/li/a не вызывает оптимизма. И мы, кстати, рекомендуем, не пользоваться подобными инструментами.
Минус №3. При всей мощности XPath остаются вопросы, которые он не может решить. Например, на XPath не получится сделать селекторы к псевдоклассам, и содержимому Shadow DOM. Но, как говорится, каждому инструменту — своя сфера применения.
С плюсами XPath все гораздо проще, ведь они очевидны и лежат на поверхности:
Плюс №1. Возможность поиска по тексту элемента. Первое, что мы встречаем в любом web-приложении — это текст. Текст в том числе располагается на кнопках, ссылках, выпадающих меню. И если свойства таких элементов могут измениться, то текст чаще всего останется прежним. Таким образом, даже изменения верстки никак не повлияют на XPath-селекторы.
Как следствие, через XPath можно искать элементы с изменяемым текстом. Например, если нужно выбрать в календаре «позавчера», можно прописать дату в явном виде в селекторе XPath. Также благодаря этой функции появляется возможность создавать селекторы для сложных таблиц. Например, это будет полезно, если вам необходимо выбрать ячейку в некой строке, причем строку и столбец можно найти только по тексту, так как номера строки и столбца могут меняться.
Плюс №2. Наличие встроенных функций, таких как contains (), starts-with (), sibling, normalize-space () и прочих в совокупности с логическим операторами and, not, or позволяет создавать гибкие и универсальные локаторы.
Все это очень полезно, когда речь заходит о реальной практике. Вот 3 примера, в которых преимущества XPath видны, так сказать, невооруженным взглядом:
Пример №1. Селектор авторских постов в блоге
Берем первый попавшийся html код.
Как я провел лето
Ходили купаться
С друзьями
Давайте напишем селектор для
Ходили купаться
Если делать это через CSS, то селектор будет выглядеть так: .second
Но обратите внимание, что у post1 и post3, нет классов first и third! Чем руководствуются разработчики подобной верстки и какие у них мотивы — мы не узнаем никогда, но с определенной долей вероятности можем утверждать, что скоро класса second тоже не будет и значит наши тесты упадут.
Сохраняя приверженность CSS, можно переписать селектор на: #post2 .title
Да, такой селектор будет жить…но вполне возможно, что тоже не долго.
Мы видим из кода, что речь идет о постах, авторских статьях или блоге. Но что будет, когда автор добавит очередной текст? Ведь логично, что новый пост должен быть первым, и тогда нумерация сдвинется, наш селектор #post2 .title будет ссылаться на пост с заголовком Как я провел лето. А неправильный селектор ещё хуже, чем нерабочий селектор, потому что узнаем мы о неправильном селекторе не сразу, если вообще узнаем.
Тем временем, на XPath селектор может выглядеть следующим образом:
//[normalize-space(.)='Ходили купаться' and contains(@class, 'title')]
Выглядит громоздко. Но сколько плюсов:
Мы привязали селектор к самому тексту заголовка, который никто не вправе изменять, кроме автора.
Верстальщик может без последствий добавлять/изменять список применяемых классов — селектор останется рабочим.
И последняя, но очень важная возможность: Представьте, что перед вами задача не написать тест и селекторы, а отредактировать селектор в существующем тесте…, на проде…, срочно, а ещё лучше вчера…
Что проще найти и изменить, например в тысяче строк кода?
Вариант 1:
Вариант 2:
Для нас очевиден Вариант №2.
Пример №2. Поиск по DOM-дереву
Возможность поиска элементов по DOM-дереву вниз или вверх позволяет использовать XPath, чтобы добраться до самых глубоко спрятанных элементов страницы.
Здесь мы оттолкнулись от существующего поля name, ушли вверх по дереву, а затем вернулись к нужным тегам. Замените значение поля name и название опции на переменные и селекторы будут универсальны для любого из меню на странице.
Пример №3. XPath справляется там, где другие не справляются
Таблицы довольно часто встречаются на web страницах. При этом нередко речь заходит о множестве таблиц на одной странице, а каждая из них может содержать сотни строк.
Как сделать селектор к ссылке ячейки «На согласовании»? Классы остались где-то наверху, теги все одинаковые, атрибутов нет от слова «совсем»…XPath тут справляется «на ура», благодаря своим функциям и полнотекстовому поиску:
Такой селектор легко читается, а значит в него легко внести правки, если это необходимо.
Кстати, тут XPath демонстрирует дополнительную гибкость. Если в примере выше «На согласовании» будет целое множество «Закупок», то мы сможем добавить номер закупки как ещё одно условие. Например, вот так:
Фактически XPath похож на язык программирования: хороший XPath-селектор легко читаем, по нему сразу ясно, о каком элементе идет речь. Такое положение дел добавляет удобства в работе с XPath, увеличивает скорость выполнения типовых задач и, как следствие, сокращает время разработки.
К тому же XPath позволяет осуществлять поиск вообще по любому атрибуту элемента. Разработчики зачастую добавляют свои атрибуты ко множеству тегов. Через CSS и стандартными методами фреймворков тестирования их не найти. XPath здесь тоже выручает, например, вот так можно сделать селектор по кастомному атрибуту:
//input[@data-input-type='SNILS’]
Подводя итог, скажу, что мы выбрали для себя XPath как наиболее удобное средство для создания селекторов и рады поделиться своим опытом как с заказчиками, так и с коллегами «по цеху». Но не любой селектор, написанный на XPath однозначно хорош. В следующем посте я подробно расскажу о «плохих» и «хороших» практиках использования XPath, которые мы определили, набивая свои собственные шишки. А сейчас прошу всех заинтересованных поучаствовать в нашем опросе.