I’ve observed that the XPath locators mastering can challenge many individuals, including junior and mid-level automation engineers. This issue often stems from various sources, such as:
- Inexperience in mastering locators for automation.
- A reliance on browser extensions that generate “ready-to-use” locators, which are then copied and pasted into test code.
- A perception that XPath Locators are inherently unreliable leads to their avoidance of test scripts.
- It’s laziness because your developers added test attributes for everything in the DOM.
In this guide, I provided approaches and examples to help you build reliable XPath Locators for your automated tests.
XPath mastering
Let’s begin with the Wikipedia main page and imagine that you need to verify the presence of the ‘Free textbooks’ text within the Wikibooks block in our automated test.
The most straightforward approach is copying the pre-built XPath locator using the browser’s developer tools, as shown in this image.
The XPath you’ll get from the browser’s dev tool will look like:
//*[@id="www-wikipedia-org"]/div[7]/div[3]/div[4]/a/div[2]/span[2]
I have also tried one of the most popular Chrome extensions for getting the XPath locator for use with Selenium, and I get this:
/html[1]/body[1]/div[2]/div[1]/div[3]/main[1]/div[3]/div[3]/div[1]/div[4]/div[2]/div[1]/ul[1]/li[4]/div[2]
If you try to use such XPath locators, you’ll find the element, of course, so these locators definitely work, but this fact does not make them reliable.
This locator is terrible for several reasons:
- Readability: The long chain of element indices and positions makes it easier to grasp the selection context if you thoroughly analyze the HTML structure.
- Fragile to Changes: Any change to the structure, such as adding or removing elements before the target element, would require updating the entire XPath, making maintenance challenging.
- Performance: XPath expressions that traverse many levels of the DOM can be slower to execute, impacting the efficiency of your automated tests.
To create more reliable XPath locators, I advise using more stable attributes like unique IDs, classes, or other attributes specific to your target element.
Feel free to check my Common XPath Methods With Examples article, where you can find the explanations for standard XPath methods with examples.
Common XPath Methods With Examples
This tutorial will clarify various methods for selecting elements and data within XML or HTML documents. I’ve included…
Let’s look a little closer to our desired element’s code.
<div class="other-project">
<a class="other-project-link" href="//www.wikibooks.org/">
<div class="other-project-icon">
<div class="sprite svg-Wikibooks-logo_sister"></div>
</div>
<div class="other-project-text"> <span class="other-project-title jsll0n" data-
jsllOn="wikibooks. name">Wikibooks</ span>
<span class="other-project-tagline jsll0n" data-jsl10n="wikibooks.slogan">Free
textbooks</span>
</div>
</ a>
</div>
There are several approaches to selecting the element.
For instance, you can notice the <data-jsl10n> attribute in this code. This unique attribute addresses exactly the slogan text element, so you can find it using the attribute selection in XPath, which involves choosing elements within an XML or HTML document based on their attributes’ values.
//*[@data-jsl10n = 'wikibooks.slogan']
This XPath Locator is considered reliable for the following reasons:
- Specificity: The XPath expression is very specific in its selection. It looks for elements anywhere in the document that have an attribute <data-jsl10n>with the value <wikibooks.slogan>. This means it’s likely to avoid accidentally selecting other elements in the document, ensuring precision.
- Independence of Structure: Unlike selecting elements based on their position or hierarchy in the document, which can be fragile if the structure changes, this XPath locator relies on a specific attribute value, making it less susceptible to changes in its structure.
- Clear and Readable: The XPath expression is clear and easy to understand, making it a reliable choice for selecting the intended element. It explicitly mentions the attribute and its value, which enhances code readability and maintainability. For this exact case, such a locator seems the most relevant.
Alternatives
Sometimes, there may be a more convenient selection for your tests. In such cases, it’s essential to find alternative selections that are also reliable.
The <Free textbooks> text is stored inside the <span> element with the <other-project-tagline jsl10n> <class> name. In this case, you can select the <@class> attribute name.
//*[@class = 'other-project-tagline jsl10n']
This XPath is still fragile because it searches for an element with an exact class attribute value of <other-project-tagline jsl10n>. If the <class> attribute for an element contains additional classes or if there are any leading or trailing spaces, this XPath would not match those elements. You can make it stronger by using the <contains> method:
//*[contains(@class, 'other-project-tagline')]
Using the <contains> method instead of the exact <class> name allows you to locate elements that contain the <class> <other-project-tagline> anywhere within their <class> attribute. This approach is more robust because it will match elements with <class> values like <other-project-tagline jsl10n> and <jsl10n other-project-taglineor> as well as any other combination where <other-project-tagline> is present.
Return to our Wikipedia page and check our new XPath locator using the devtool search.
Now, you’ll be able to find the desired text element. However, since this page contains thirteen <other-project> elements, our XPath locator selects all of them. The simplest, though not the most robust, way to address this is by using the positional selection in XPath, which involves choosing elements within an XML or HTML document based on their position or index in the document’s structure.
Since our desired Wikibooks is the fourth element within its block, you can append [4] to our XPath locator:
(//*[contains(@class, 'other-project-tagline')])[4]
Using an index like [4] in your XPath locator can be considered as not reliable enough because if the structure of the web page changes, such as adding or removing elements before or within the block you are targeting, the index may no longer point to the correct element.
Depending on your specific interaction requirements for these elements in your test, you can address this issue using various methods.
For example, you can use the text content selection in XPath, which refers to choosing elements within an XML or HTML document based on the textual content contained within those elements. You can combine it with our previous attribute selection using the logical operators.
//*[contains(@class, 'other-project-tagline') and text() = 'Free textbooks']
This XPath will locate elements with the class <other-project-tagline> with the exact text content of <Free textbooks>.
There are better solutions than this because UX designers or SEO specialists can change the text, so keep it in mind when using text-based locators.
But what if you want to locate this element to verify its text value? For this case, the text value-based locator is irrelevant.
Back to our code.
<div class="other-project">
<a class="other-project-link" href="//www.wikibooks.org/">
<div class="other-project-icon">
<div class="sprite svg-Wikibooks-logo_sister"></div>
</div>
<div class="other-project-text"> <span class="other-project-title jsll0n" data-
jsllOn="wikibooks. name">Wikibooks</ span>
<span class="other-project-tagline jsll0n" data-jsl10n="wikibooks.slogan">Free
textbooks</span>
</div>
</ a>
</div>
You can also find that each <other-project-text> block includes the <tagline>element you’re trying to pick and the preceding sibling title element with unique text inside. You can add this preceding sibling element to our XPath Locator:
//*[contains(@class, 'other-project-tagline')]/preceding-sibling::*[text() = 'Wikibooks']
This XPath locator can find an HTML element with a class attribute containing other-project-text immediately preceded by a sibling element with the text Wikibooks within the same parent element. However, remember that if the order of elements inside the parent div changes, your locator can be broken.
Conclusions
We aimed to find a reliable XPath locator for a given text element. First, I tried to get the ready-to-use XPath locators using the browser’s developer tools and some of the most popular browser extensions for UI automation, and this is what I got:
Chrome DevTool:
//*[@id="www-wikipedia-org"]/div[7]/div[3]/div[4]/a/div[2]/span[2]
One of the most popular Chrome extensions:
/html[1]/body[1]/div[2]/div[1]/div[3]/main[1]/div[3]/div[3]/div[1]/div[4]/div[2]/div[1]/ul[1]/li[4]/div[2]
Since these ready-to-use locators seem terrible, we have found multiple approaches to master the reliable and readable XPath locators.
Let’s review them again and compare them with a given by dev tools and extensions:
//*[@data-jsl10n = 'wikibooks.slogan']
or
//*[contains(@class, 'other-project-tagline') and text() = 'Free textbooks']
or
//*[contains(@class, 'other-project-tagline')]/preceding-sibling::*[text() = 'Wikibooks']
Our XPath locators look much better, the expressions are clear and easy to understand, and their reliability is much stronger.
I hope this article helps you in your automation journey and that this knowledge strengthens your automated tests.
2 thoughts on “How to master reliable XPath locators for your automated tests”