Ответ
XPath (XML Path Language) — это язык запросов для навигации по узлам XML/HTML-документа.
Преимущества XPath:
- Мощь и гибкость: Позволяет создавать очень специфичные локаторы, недоступные для CSS-селекторов.
- Поиск по тексту:
//button[text()='Submit'] - Поиск по частичному совпадению атрибута:
//div[contains(@class, 'panel')] - Навигация по осям:
//input[@id='field']/following-sibling::div - Использование логических операторов:
//input[@type='text' and @required]
- Поиск по тексту:
- Универсальность: Работает с любым корректным XML/HTML, независимо от того, как он отрендерен. Это особенно полезно для сложных или динамически генерируемых DOM-деревьев.
- Поддержка: Реализован во всех основных инструментах автоматизации (Selenium, Playwright, Cypress, Appium).
Недостатки XPath:
- Хрупкость (Fragility): Локаторы, сильно зависящие от структуры DOM (например, с использованием индексов
[1],[2]), легко ломаются при малейшем изменении верстки. - Производительность: В общем случае XPath-запросы могут выполняться медленнее, чем CSS-селекторы, особенно в больших документах и при использовании сложных осей (например,
ancestor,preceding). Современные браузеры оптимизировали эту разницу, но она все еще может быть заметна. - Читаемость и поддержка: Сложные XPath-выражения могут быть длинными и трудными для понимания, что усложняет поддержку тестов.
Практические рекомендации:
- Предпочитайте CSS-селекторы для простых случаев (по id, классу, атрибуту). Они обычно быстрее и читабельнее.
# CSS driver.find_element(By.CSS_SELECTOR, "button.primary[type='submit']") - Используйте XPath, когда CSS недостаточно (поиск по тексту, сложная навигация).
# XPath driver.find_element(By.XPATH, "//button[contains(text(), 'Save changes')]") - Избегайте абсолютных путей (
/html/body/div...) и индексов. Стройте относительные и устойчивые локаторы, используя уникальные атрибуты (id,data-testid) и функции типаcontains().# ПЛОХО: Хрупкий By.XPATH("/html/body/div[2]/div[3]/button[1]") # ЛУЧШЕ: Относительный и устойчивый By.XPATH("//form[@id='login-form']//button[@type='submit']")
Ответ 18+ 🔞
А, XPath, ёпта, ну это ж классика, как "Муму" у Тургенева, блядь! Сидишь такой, смотришь на эту верстку — лес дремучий, сука, узлов дохуя, а тебе надо кнопку найти, которая спрятана, как последняя совесть у Герасима.
XPath — это типа такой язык, чтобы шастать по этим XML/HTML-деревьям, как по своему огороду. Нашёл лопату — копай, куда хочешь.
Чем он, блядь, хорош, этот ваш XPath?
- Сила — просто овердохуища! CSS-селекторы рядом не стояли, честно. Нужно найти кнопку по точному тексту? Пожалуйста:
//button[text()='Submit']. Нужно найти див, у которого в классе хоть где-то затесалось слово 'panel'? Да не вопрос://div[contains(@class, 'panel')]. Можно, сука, по родственным связям лазить: «Дай мне див, который идёт после этого инпута» —//input[@id='field']/following-sibling::div. А можно ещё и с логикой поиграться://input[@type='text' and @required]. В общем, полная свобода, блядь, почти как в те времена, пока барыня не приказала Муму утопить. - Универсальный он, зараза. Ему похуй, как там браузер эту разметку склепал — динамически, на коленке, с блэкджеком. Если это валидный XML/HTML, XPath его прочитает. Спасение в тёмном лесу сложного DOM'а.
- Везде его, подлеца, поддерживают. Selenium, Playwright, Cypress, Appium — все, как один, его понимают. Стандарт, блядь, де-факто.
А теперь, блядь, ложка дёгтя, размером с ту самую гирю, которой можно и нечаянно ебнуть:
- Хрупкий, сука, как ёлочная игрушка! Особенно если строить локаторы на индексах, типа
[1],[2]. Разработчик чихнёт, добавит один лишнийdiv— и всё, пиздец вашему тесту, локатор сломался. Совесть, блядь, потом заест, как Герасиму. - Может тормозить, зараза. В общем-то, XPath-запросы обычно медленнее CSS-селекторов, особенно если документ большой, а запросы — с причудами (типа
ancestor,preceding). Браузеры, конечно, поумнели, разницу сгладили, но осадок, как говорится, остаётся. - Читаемость — ноль ебать. Глянешь на строку в полэкрана, всякую хуйню с осями — и волнение ебать чувствуешь. Потом через месяц сам не поймёшь, что эта хитрая жопа искала.
Так что же делать-то, ёпта? Практические советы, чтобы не обосраться:
- Для простых случаев — CSS, и не выёбывайся. Поиск по id, классу, атрибуту — это их стезя. Быстро и понятно.
# CSS — чисто, аккуратно, в садок польёт driver.find_element(By.CSS_SELECTOR, "button.primary[type='submit']") - А вот когда CSS пасует — тут XPath в дело. Нужно по тексту искать или через три колена перелезть — вот его царство.
# XPath — когда надо докопаться до сути driver.find_element(By.XPATH, "//button[contains(text(), 'Save changes')]") - Забудь, блядь, про абсолютные пути, как страшный сон! Никакого
/html/body/div[2]/div[3]/button[1]. Это путь в никуда и к поломанным тестам. Дружи с относительными путями и уникальными атрибутами вродеdata-testid. Функцияcontains()— твой друг.# ПЛОХО: Хуйня полная. Сломается от чиха. By.XPATH("/html/body/div[2]/div[3]/button[1]") # ЛУЧШЕ: Умно, гибко, не привязано к индексам, как собака на цепи. By.XPATH("//form[@id='login-form']//button[@type='submit']")
Вот и вся философия. Выбирай инструмент по ситуации, а не потому что «так исторически сложилось». А то получится, как с Герасимом — вроде всё правильно делал, а в итоге всех замочил и сам с тоски в деревню свалил.