How to drop XPath

There are about 100 vacancies on the hh.ru website where the skill of compiling XPath is important for the employer, and the Internet is full of materials, such as cheat sheets on compiling locators or workshops on YouTube. Somehow I was asked at an interview about which of the languages ​​for constructing locators is better to use XPath vs CSS, and I answered that it is better to use test attributes, and if we use them, then it is not necessary to use these languages. Most likely, such an answer did not suit, but I answered honestly, because in the previous place we tried not to use XPath to solve this problem.

Crib

Crib

What is this XPath Beast

XPath (XML Path Language) is a path language that uses a syntax other than XML to address different parts of an XML document. There are several standards for this language, XPath 3.1 – published in 2017 (with support for maps, arrays and JSON).

XPath selectors are commonly named “xpaths” and a single xpath specifies the destination from the root to the desired endpoint.

Operators

  • Operators and ///[...]

  • node union operator, |

  • Boolean operators andAnd orand functionnot()

  • Arithmetic operators +, -, *, div Andmod

  • Comparison Operators =, !=, <, >, <=>=

Functions

concat(), substring(), contains(), substring-before() and more

How it is used in tests

In tests, we are forced to interact with elements of the HTML page, and for this we need selectors to access buttons, input forms, and other elements of the web interface.

For example, we have a simple html document, and we need to refer to the element a, which is inside a 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
You can check the locator through the browser console $$('');  for CSS, $x('');  for XPath

You can check the locator through the browser console $$(”); for CSS, $x(”); for XPath

In tests, we can refer to this locator like this

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"));

Why we use it and why it’s not very

I will assume that there are several reasons why this approach is still used:

  • historically it has been

  • the frontend is not prepared for the development of autotests (the developers did not provide test locators-attributes), we get out with requests with conditions

If the reason is the lack of unique test attributes and we build the locator based on the conditions, most likely we are creating an unstable locator, no matter how well it is composed.

If we are tied to the name of the class, then at any time it can change, for example, when rebuilding the webpack, and when the location changes or when wrapped in a new tag, the path will change and the locator will be invalid.

For tests, we need a stable, unique locator, for this the correct solution is to use a test attribute.

Benefits of Using Test Attributes

  • increases stability, because conditions, functions are not used

  • support for automatic numbering (for multiple objects of the same type)

Of the minuses – parsing is simplified if the locator is available from the outside.

Support for test attributes by popular frameworks

framework

usage

test attributes

playwright

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

If no decision has been made within the company about a custom name for test attributes, then you can use data-testidwhich is supported and recommended by most frameworks for use.

Selenium does not support test attributes out of the box, but you can get out like this, and in the future, you can support the test name inside the project

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

How to arrange test locators

The simplest solution is to create a task for finalizing the frontend, and throw it into the backlog, and then, when planning, take it to the sprint, according to priority. But, if you have free time and desire, you can independently locally raise and tinker with the frontend. Pay attention to the component, if it exists.

Option one (and easiest) – adding the locator directly

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>
 );
}

Or you can add data-testid to the component itself and pass the value when using the component dataTestId

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

Outcome

  • building locators using all the features of XPath / CSS – based on class names, nesting, and everything that can change at any time – is bad

  • for automation, it is desirable to use unique test attributes

  • for test attributes, you can use the name data-testidwhich is supported by several frameworks

  • to access these test locators, you can use internal methods or access through [data-testid=”имя локатора”] using By.CSS/By.Xpath methods

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *