Избыточный XPath (Excessive XPath)
Для поиска элементов используются сложные XPath-выражения: абсолютные пути, позиционные индексы, конкатенация с contains() и normalize-space(), — там, где достаточно простого CSS-селектора.
Симптомы
- Абсолютный XPath:
/html/body/div[1]/div[2]/main/section/div[3]/input - Позиционные индексы:
//ul/li[3]/div[2]/span - Сложные предикаты:
//button[contains(@class,'btn') and normalize-space(text())='Сохранить'] - XPath длиннее 80 символов
- Локаторы скопированы из «Copy XPath» в DevTools без изменений
Причины возникновения
- «Copy XPath» в браузере — самый простой способ получить локатор прямо сейчас
- Нет атрибутов
data-testidв вёрстке, поэтому выбирают XPath как «единственный вариант» - Непонимание возможностей CSS-селекторов (
:nth-child,[attr^=val],~,+) - Убеждение, что XPath мощнее и поэтому лучше
Почему это проблема
-
Хрупкость: любое изменение структуры DOM — добавление
<div>обёртки — ломает абсолютный XPath - Медленная выборка: браузерный движок обрабатывает XPath медленнее CSS в 2–5 раз
-
Нечитаемость:
/html/body/div[1]/div[3]/main/...невозможно понять без открытия DevTools - Ошибки при копировании: автоматически скопированный XPath почти всегда абсолютный и сразу устаревает
Решение
CSS-селектор по стабильному атрибуту, XPath — только там, где CSS не справляется:
// ❌
By.xpath("/html/body/div[1]/div[2]/main/section/div[3]/input")
By.xpath("//button[normalize-space(text())='Сохранить']")
// ✅
By.cssSelector("[data-testid='email-input']")
By.cssSelector("[data-testid='save-btn']")
// XPath уместен только для поиска по тексту без атрибутов
By.xpath("//label[text()='Обязательное поле']")