XPath's selectors— and nothing else matter…

mati-qa
4 min readOct 17, 2023

--

Each time I start a new project, there seems to be no ID, no dataTestId, nor data-aria — nothing unique that could help me make easy selectors for my e2e tests. How do I deal with that?

Intro

Back in the time, I was trying to use built-in methods that could localize the stuff based on the label, class, roles, and so on — which is the easiest, but… it turned out that it is very flaky and can be easily used only in the simplest cases. Here is how it looks in the case of Playwright (locators):

As you can see, it looks awesome, but try using it in more complicated cases. And here it is worth mentioning XPath (by the way, there are also CSS selectors, but in my humble opinion, they are not as powerful as XPath — just my opinion!). XPath is awesome, if you understand the syntax. It can be used in the browser console, which allows you to easily validate the selector.

What is XPath?

(XML Path Language) is an expression language designed to support the query or transformation of XML documents. It was defined by the World Wide Web Consortium (W3C) in 1999,[1] and can be used to compute values (e.g., strings, numbers, or Boolean values) from the content of an XML document. Support for XPath exists in applications that support XML, such as web browsers, and many programming languages. Wikipedia

That’s all about the theory, even though it may sound a bit weird. Let’s go to some use cases. There are many tutorials on the web that can help you learn this awesome language. Here I’ll only show you a few examples that often help a lot and can save you some time.

Use cases

My favourite approach is to go from the details (particular element) to the element you need to handle. To catch the element (wherever in the page), e.g., a div with the particular class, e.g., table-cell, you need to write:

//div[@class="table-cell"]

Double slash means “find any div element (on the page) whose class equals table-cell.” What if we would like to find an element that contains some class? No problem:

//div[contains(@class, "table-cell")]

The same construct can be applied to any HTML tag (e.g., th, tr, span, label, etc.). But yeah, these are simple cases. The real power comes when you’re trying to play with the axes, as XPath allows you to navigate in different directions starting from your “handle.” What is possible? Almost everything. Have a look:

https://www.w3schools.com/xml/xpath_axes.asp

Imagine we need to gather the read time and publication date from the main Medium page (without logging in), for one of the trending articles. For example, the one marked on the screen below:

Looking at the browser inspector… there is nothing obvious:

Of course, we could try to generate a selector using the build in option in the browser (right-click on the element and then CSS or XPath):

Have a look on that…

CSS:

div.fs:nth-child(2) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > span:nth-child(3)

XPath:

/html/body/div[1]/div/div[4]/div[1]/div/div/div/div[2]/div/div[2]/div/div/div[2]/span

As you can see, it’s hard to read that, and all of those are based on the numbers of elements (e.g., nth-child(2), div[4]). How can we simplify this and make it more readable? Of course, using axes. Take a look at this example:

And there is how the XPath look like:

//h2[text()[contains(.,"San Francisco")]]/ancestor::div[contains(@class, "ij ah")]/following-sibling::span

So, what we’re doing here is localizing any h2 element that contains the text “San Francisco” — this is our “root”. Then we’re going to its ancestor div element (the element above it in the DOM), which has the class ij ah. And the last move is to the following sibling span element, which should be a single level lower (a single slash means “right below”).

Summary

I hope this simple example shows the power of XPath, especially when you have no dedicated tags, IDs, or other unique values that can distinguish the elements in the DOM. Also, I think the syntax is pretty understandable, even if you haven’t worked with XPath for a long time. So, have fun and experiments! ;)

--

--

No responses yet