Как отказаться от XPath/CSS локаторов в тестах

от автора

На сайте hh.ru есть около 100 вакансий, где навык составления XPath важен для работодателя, также в интернетах полно материалов, вроде шпаргалок по составлению локаторов или ворк-шопов на ютубе. Как-то у меня спросили на собеседовании про то, какой из языков построения локаторов использовать лучше XPath vs CSS, и я ответил — лучше использовать тестовые аттрибуты, а если мы их используем то и использовать эти языки необязательно. Скорее всего такой ответ не устроил, но я ответил честно, т.к на предыдущем месте мы старались не использовать XPath для решения этой задачи.

Шпаргалка

Шпаргалка

Что это за зверь XPath

XPath (XML Path Language) — это язык путей, использующий синтаксис, отличный от XML, для обеспечения адресации различных частей XML-документа. Существует несколько стандартов данного языка, XPath 3.1 — опубликован в 2017 году (с поддержкой карт, массивов и JSON).

Селекторы XPath обычно называются «xpaths», и один xpath указывает пункт назначения от корня до желаемой конечной точки.

Операторы

  • Операторы и /, ⁣//[...]

  • Оператор объединения узлов, |

  • Булевы операторы andи or, и функцияnot()

  • Арифметические операторы +-*div иmod

  • Операторы сравнения =!=<><=, ⁣>=

Функции

concat(), substring(), contains(), substring-before() и многое другое

Как это используется в тестах

В тестах мы вынуждены взаимодействовать с элементами HTML-страницы, а для этого нам нужны селекторы, чтобы обращаться к кнопкам, формам ввода, и другим элементам веб-интерфейса.

К примеру, у нас есть простой html-документ, и нам нужно обратиться к элементу а, находящемуся внутри div

<head>     <title>Xpath & CSS</title> </head> <body> <h1>Hello World</h1> <p>some description text: </p> <div>         <a class="link" href="https://helloworld.com">example link</a> </div> </body>

XPath-selector

/html/body/div[1]/p/a

CSS-selector

body > div > a
Проверить локатор можно через консоль браузера $$(''); для CSS, $x(''); для XPath

Проверить локатор можно через консоль браузера $$(»); для CSS, $x(»); для XPath

В тестах можем обращаться к этому локатору так

WebElement passwordByXPath = driver.findElement(By.xpath("/html/body/div[1]/p/a"));  //или вот так WebElement passwordByXPath2 = driver.findElement(By.xpath("//a[contains(text(),"example link")]"));  WebElement passwordByCSS = driver.findElement(By.css("body > div > a"));

Почему этим пользуемся и почему это не очень

Предположу что есть несколько причин, по которым этот подход еще используется:

  • исторически так сложилось

  • фронтенд не подготовлен для разработки автотестов (разработчики не предусмотрели тестовые локаторы-аттрибуты), выкручиваемся запросами c условиями

Если причиной является отсутствие уникальных тестовых аттрибутов и мы строим локатор, исходя из условий, скорее всего мы создаём нестабильный локатор, в не зависимости от того, насколько правильно он составлен.

Если мы завязались на название класса, то в любой момент он может измениться, например при пересборке веб-пака, а при изменении расположения или при оборачивании в новый tag — изменится путь и локатор будет невалидным.

Для тестов нам нужен стабильный, уникальный локатор, для этого правильным решением будет использовать тестовый аттрибут.

Преимущества использования тестовых аттрибутов

  • повышается стабильность, т.к не используются условия, функции

  • поддержка автоматической нумерации (для множественных объектов одного типа)

Из минусов — упрощается парсинг, если локатор доступен извне.

Поддержка тестовых атрибутов популярными фреймворками

фреймворк

использование

тестовые аттрибуты

Playwrigth

page.getByTestId(‘directions’).click();

data-pw
data-testid

Cypress.io

cy.get(‘[data-cy=»submit»]’).click();

data-cy
data-test
data-testid

WebdriverIO

$(‘button[data-testid=»submit»]’)

data-testid

Если внутри компании не принято решение о кастомном названии для тестовых аттрибутов, то можно использовать data-testid, которое поддерживается и рекомендуется большинством фреймворков для использования.

В Selenium из коробки отсутствует поддержка тест-аттрибутов, но можно выкрутиться вот так, а в дальнейшем, можно поддержать тестовое название внутри проекта

driver.findElement(By.css('[data-testid="entry-btn"]')

Как расставить тестовые локаторы

Самое простое решение — создать задачу на доработку фронтенда, и закинуть в беклог, а затем при планировании, взять её в спринт, согласно приоритету. Но, если есть свободное время и желание, можно самостоятельно локально поднять и поковырять фронтенд. Обратить внимание на компонент, если он существует.

Вариант первый (и самый простой) — добавление локатора напрямую

import React, { Component } from 'react'; import { Button } from "@material-ui/core";  function ViewIntro({ onOrder }) {  return (  <Button    variant=”contained”    color=”primary”    data-testid=”entry-btn” //просто добавляем аттрибут здесь и проверяем через консполь   onClick={onOrder}>  Order your ?  </Button>  ); }

А можно добавить data-testid в сам компонент и при использовании компонента передать значение dataTestId

const Component = ({ variant, color, dataTestId, onOrder }) => (    <Button      variant={variant}      color={color}      data-testid={dataTestId}     onClick={onOrder}>     Order your ?  </Button> );

Итог

  • строить локаторы, используя все возможности XPath/СSS — на основе названий классов, вложенности, и всего, что может в любой момент измениться — плохо

  • для автоматизации желательно использовать уникальные тестовые атрибуты

  • для тестовых атрибутов можно использовать название data-testid, которое поддерживается несколькими фреймворками

  • для обращения к этим тестовым локаторам можно использовать внутренние методы или обращаться через [data-testid=»имя локатора»] используя методы By.CSS/By.Xpath


ссылка на оригинал статьи https://habr.com/ru/articles/742088/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *