среда, 29 мая 2024 г.

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

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

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

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

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

(там таблички нормально отрисовываются и есть содержание кликабельное)



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

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::*

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

PS — статья написана в помощь студентам моего курса «CSS и Xpath: инструменты тестировщика».

Комментариев нет:

Отправить комментарий