XPATH или CSS локаторы - что лучше?

26-02-2020

Использование CSS или XPATH локаторов в большинстве случаев является делом вкуса и привычки. Хорошие знания одного из этих инструментов будут достаточным условием, например, для автоматизации веб-приложений.

Тем не менее, следует знать некоторые особенности и ограничения обоих инстурментов.

  1. XPATH - мощный и универсальный инструмент, знание которого спасёт в любой ситуации, связанной с поиском элементов, однако за его мощь нужно будет заплатить производительностью.
  2. CSS-локаторы были разработаны специально для HTML, а XPath-локаторы - это универсальный механизм для поиска по XML DOM. Поэтому для CSS идентификатор и имя - это особые атрибуты, он строит табличку-индекс для быстрого обращения к элементам, снабженным этими атрибутами. Поскольку эти атрибуты должны быть уникальными, индексация работает очень эффективно. А с точки зрения XPath - это "просто атрибуты", поиск ведётся не по таблице-индексу, а по всему DOM-дереву. Поиск по классу уже не так эффективен.
  3. В большинстве случаев локатор на CSS выглядит лаконичнее и дружелюбнее чем локатор на XPATH.
  4. В старых версиях IE XPATH отрабатывал значительно медленне CSS поскольку возможность использования XPATH осуществлялась с помощью JavaScript.
  5. XPATH движки различны для разных браузеров.

Что умеет XPATH и не умеет CSS:

  1. СSS не умеет "ходить" вверх по дереву DOM.
  2. Поиск по тексту невозможен в CSS.
  3. В XPATH возможны подзапросы.

Советы по использованию XPATH:

  1. Постарайтесь избегать абсолютных путей в XPATH запросах.
  2. Старайтесь не использовать цифры.
  3. Не используйте длинные XPATH.
  4. Cтарайтесь не использовать * перед квадратными скобками.
  5. Cтарайтесь не использовать подзапросы.

Пару примеров для сравнения синтаксиса

Пример CSS 3 XPATH
Все элементы * //*
Все < p> элементы p //p
Все child элементы p>* //p/*
Поиск по ID #foo //*[@id=’foo’]
Поиск по классу .foo //*[contains(@class,’foo’)]
Поиск по атрибуту *[title] //*[@title]
Первый child всех < p> p>*:first-child //p/*[0]
Все < p> элементы с дочерним < a> -невозможно найти- //p[a]
Следующий элемент p + * /p/following-sibling::*[0]
Предыдущий элемент -невозможно найти- //p/preceding-sibling::*[0]

Теперь, имея эти знания

"Думайте сами, решайте сами ..."