Для написания автотестов используются 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 — больше полезных статей ищите в моем блоге по метке «полезное». А полезные видео — на моем youtube-канале