Разделы портала

Онлайн-тренинги

.
Шпаргалка по XPath и CSS-селекторам
02.07.2024 00:00

Автор: Ольга Назина (Киселёва)

Для написания автотестов используются XPath и CSS-селекторы. Они помогают найти элемент на странице, чтобы потом с ним как-то взаимодействовать (кликнуть, ввести текст, или что-то другое).

Я видела много статей о том, что это вообще такое, но мне очень не хватало шпаргалки по разным селекторам, причем в разрезе «Вот он в CSS и он же в XPath» для сравнения. 

А мне такое для студентов надо. Поэтому решила сделать сама. Вдохновлялась страничкой «Xpath cheatsheet», но сделала на свой вкус — под автоматизацию, а не XPath вообще. И с комментариями, с ними удобнее. 

Пишите, если где-то накосячила. Хотя я все селекторы проверяла на тестовых страницах, но мало ли… И надеюсь, вам такая шпаргалка тоже пригодится! =)

Содержание

  1. Поиск конкретного элемента

  2. Поиск по атрибутам

  3. Поиск по тексту элемента

  4. Поиск по позиции элемента

  5. Поиск потомков (обход дерева вниз)

  6. Поиск предков (обход дерева вверх)

  7. Поиск соседей

  8. Поиск по комментариям

Поиск конкретного элемента

CSS

XPath

Комментарий

*

//*

Найти любой элемент (используется обычно как часть более сложного запроса)

div

//div

Найти элемент div

div:nth-of-type(2)

//div[2]

Найти 2-ой элемент div под общим родителем (вместо 2 может быть любая цифра) 

В CSS используется псевдокласс, в firefox он не срабатывает, в хроме тоже может глючить. В этом сценарии xpath лучше

Поиск по атрибутам

CSS

XPath

Комментарий

Любой элемент

.form-control

//*[@class="form-control"]

Элемент с классом form-control

#sample_1

//*[@id="sample_1"]

Элемент с атрибутом id = sample_1

[id]

//*[@id]

Элемент с атрибутом id, значение у атрибута любое




Конкретный элемент (в примере это div, но искать можно любой)

div.form-control

//div[@class="form-control"]

Именно div элемент с атрибутом class=form-control

div#sample_1

//div[@id="sample_1"]

Именно div элемент с атрибутом id = sample_1

div[id]

//div[@id]

Именно div элемент с атрибутом id 

div[attr]:nth-child(2)

//div[2][@attr]

2-ой элемент div с атрибутом attr под общим родителем

XPath найдет такой div, даже если между 2-мя div-ами будет что-то ещё. А вот CSS нет (см тут подробнее), только если подряд идут. Поэтому с потомками лучше через XPath

h1:not([id])

//h1[not(@id)]

Элемент h1, у которого нет атрибута id

a:is([name],[href])

//a[@name or @href]

Элемент а, у которого есть или атрибут name, или href, или оба




Сравнения по тексту атрибута (в примере это class, но атрибут может быть любым)

Есть атрибут class, проверяем текст в нем. Допустим, у нас есть такие элементы:

1. class = “test-1 test-3 test-2”

2. class = “test-1”

[class="test-1"]

[class='test-1']

//*[@class="test-1"]

//*[@class='test-1']

Текст четко равен "test-1" (тип кавычек не важен)

Найдет элемент 2, но не найдет элемент 1. 

[class~="test-3"]

//*[contains(@class, 'test-3')]

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

В XPath такого нет, поэтому там просто contains — в тексте есть искомое значение

Найдет элемент 1

[class|="test"]

//*[contains(@class, 'test')]

Полное соответствие или атрибут начинается как указано и потом идет "-" (U+002D)

Найдет и элемент 1, и элемент 2

[class^="te"]

//*[starts-with(@class, 'te')]

//*[substring-after(@class, 'te')]

Начинается на …

Найдет и элемент 1, и элемент 2.

В Xpath 2 варианта записи, substring-after ищет текст, который идет после указанного, то есть указанный должен быть.

В CSS запись как в регулярных выражениях

[class$="2"]

//*[substring-before(@class, '2')]

Заканчивается на …

Найдет только элемент 1

В Xpath ещё должно быть выражение «ends-with», но оно не работает ????

[class*="st"]

//*[contains(@class, 'st')]

Содержит искомый текст (хотя бы 1 вхождение, неважно где, начало, конец или середина строки)

Найдет и элемент 1, и элемент 2.

Поиск по тексту элемента

CSS

XPath

Комментарий

-

//a/text()[. ="Ссылка"]

Текст внутри тегов <a> равен «Ссылка»

-

//a[contains(text(),'Ссылка')]

Текст cодержит «Ссылка» (может быть частью слова)

-

//*[starts-with(text(), 'Ссы')]

//*[substring-after(text(), 'Ссы')]

Начинается на …

-

//*[substring-before(text(), 'ка')]

Заканчивается на … (одно из слов, «Ссылка 1» тоже найдет)

-

//a[string-length(text()) > 6]

Длина текста тега <a> больше 6 символов (оператор может быть любым)

Поиск по позиции элемента

CSS

XPath

Комментарий

div:first-child

//*[1][name()="div"]

Первый div

div:last-child

//*[last()][name()="div"]

Последний div




body div:last-child

//body/div[last()]

Последний div внутри body

div:nth-last-of-type(2)

//body/div[last()-1]

Предпоследний div

div:nth-of-type(-3+2)

//body/div[position()<3]

Все div от 1 до 3 (не включительно, оператор может быть любым)

div:nth-of-type(2)

//body/div[position()=2]

Конкретная позиция (2-ая, но цифра может быть любой)

CSS работает с оговорками (см тут подробнее)




div:first-of-type

//div[1]

Первый элемент div

div#id:first-of-type

//div[1][@id]

Первый элемент div с атрибутом id

div[attr]:first-of-type

//div[1][@attr]

Первый элемент div с атрибутом attr




div:last-of-type

//div[last()]

Последний элемент div

Поиск потомков (обход дерева вниз)

CSS

XPath

Комментарий

div h2

//div//h2

h2, дочерний к div (на любом уровне вложенности, div - test - h2 найдет)

div > h2

//div/h2

Прямой потомок (1 уровень вложенности, div - test - h2 уже не найдет)

div > div > h2

//div/div/h2

Спускаемся по дереву, ищем div, внутри ещё div, внутри h2 (прямые потомки везде)




body > *

//body/child::*

Дети (1 уровень вложенности) любые

body > div

//body/child::div

Дети с типом div




body *

//body/descendant::*

Все потомки с типом div (любой уровень вложенности: дети, внуки…)

body div

//body/descendant::div

Только потомки div

-

//body/descendant-or-self::* 

Сам body и все потомки




-

//head/following::*

Все, что после head идет

-

//head/following::a

Все элементы a, которые идут после head

Поиск предков (обход дерева вверх)

CSS не умеет идти по дереву наверх, тут только XPath сработает

CSS

XPath

Комментарий

-

//a/ancestor::*

Все предки ссылки - родитель, дед, прадед, на все уровни вверх смотрим (<a> — это ссылка в HTML)

-

//a/ancestor::div

Только предок div




-

//a/ancestor-or-self::*

Сама ссылка + предки

-

//a/ancestor-or-self::div

Сама ссылка + предки div

-

//a/ancestor-or-self::a

Сама ссылка + предки такого же типа (a)




*:has(> a)

//a/parent::*

Родитель ссылки (строго 1 уровень наверх)




-

//p/preceding::*

Все узлы до текущего, кроме непосредственного родителя (но зато есть те, кто идет до родителя + предки)

-

//p/preceding-sibling::*

Все узлы-соседи до текущего узла (под одним родителем)

Поиск соседей

CSS

XPath

Комментарий

h1 ~ h2 

//h1/following-sibling::h2

Все элементы h2, которые находятся после элемента h1 внутри одного родителя

h1 + h2

//h1/following-sibling::h2[1]

Только первый элемент h2, соседний к h1 справа (находится после)

В XPath можно выбрать не только первый, но и второй, третий, даже last()

h1 ~ h2:last-of-type

//h1/following-sibling::h2[last()]

Последний элемент, который находится после элемента h1 внутри одного родителя

Поиск по комментариям

CSS

XPath

Комментарий

-

//comment()

Все комментарии

-

//comment()[. = 'comment']

Комментарий с конкретным текстом

-

//comment()[. = ' comment ']/parent::*

Родительский элемент комментария