If you are an automation engineer, you have heard the word XPath many times in your life. No wonder. XPath is a vast topic and I am still discovering great things 💡
So far they have been serving us just a little over two decades and has released 03 major versions. XPath 3.1 which is a revision of 3.0 is the latest. XPath uses nodes, syntax, and axes to derive locators. Its operators can be used to return string values, boolean values, or numbers, or nodes.
Table of Contents
Why are XPaths so important?
Well, let me narrow down the question to the test automation field. Why are XPaths so important in the test automation field? In simple terms, XPath is our savior when it comes to locating elements.
IDs, names are the best locating strategies to capture elements as they are less prone to changes. However, in reality, most developers or user interface designers are reluctant to add IDs or names which is an extra effort for them. Especially if you examine front-end framework generated user interfaces, most of them are not generating any IDs or names.
Even if they are generated, they are session-specific. In other words, each ID or name is dynamic and only valid until the current session ends 🔚
Until test automation came into the spotlight, there was no necessity to add the extra effort to add IDs or names. Hence most of the applications we test do not even have them.
Therefore, the XPaths have been the main locating strategy and occupy a large portion of the locating strategies of the elements in the page object repository.
If you look closely, XPaths come in three flavors:
- Absolute XPaths
- Relative XPaths
- Exact XPaths
Absolute XPaths
Absolute XPaths start all the way from the topmost element of the DOM and traverse through until the desired element is captured. Generally, absolute XPaths are lengthy. Its disadvantages are:
- Challenging to maintain
If you are using absolute XPaths to capture elements in your object repository, you might be having 100 or even 1000 different elements relying on absolute XPaths. How do you feel right now if there is a change in the UI and introduced a <span> tag somewhere in between?
- Time consuming
Due to the maintenance overhead, there is a lot of time that needs to be invested. Apart from that, in order to derive absolute XPath, it takes a considerable amount of time compared to relative or exact XPaths.
- Not human-readable
As we keep moving down the HTML page, the length of the locator grows. Imagine you have 100 elements on the page. XPath will be exponentially long.
Example for absolute XPath:
/html/body/table/tr/td[1]/div/div/div/span/span/p/input
Note that absolute XPath starts with a single back-slash since absolute XPaths start from the root element.
Relative XPaths
As the name suggests, relative XPaths are derived relating to another existing element on the page. The element you are selecting should be stable and should be less prone to changes.
The next question that might pop into your mind is how to find the best relative element to derive the XPath? Let’s take an example to explain:
<div> <span>Name</span> <input type="text"></div>
Assume you need to capture the input field. Here the “Name” is a text appearing on the screen and is visible to the end-user. Hence is less likely to change. Therefore, <span> is a good element to act as the relative element:
//span[text()='Name']/../div/input
With practice, you will gain more experience to select the best relative element ✅
Exact XPaths
The fastest kind of XPath derived on the element taking its attributes into account. I would like to call them, self-supported XPaths, as they do not depend on any other element on the page. Below is an example:
<div> <span>Name</span> <input type="text" automationId=”automation_name” title=”username”> </span>
Assume you want to capture the input field. Here if you look closely, the input field contains several attributes we can use; automationid, type, and title attributes. Automationid seems to be a promising attribute as the name implies.
//input[@automationId=’automation_name’]
If you are still not confident, we can combine several attributes to derive a unique locator.
//input[@automationId=’automation_name’ and @title=’username’]
When you combine multiple attributes, you can derive a unique as well as a stable locator. Deriving a unique locator is essential to avoid flaky tests and interim failures during test execution.
XPath best practices to enlighten your automation suite
In this section, I am going to share a few best practices you can use when locating elements with XPaths.
- Use exact or relative XPaths as much as possible to capture elements
Selenium supports all the three different XPath types: absolute, relative, and exact XPaths. It is highly encouraged to use exact XPaths. However, in the practical world, it is not always possible. Then the next best option would be relative XPaths.
I Strongly discourage the use of absolute XPaths as I pointed out they are cumbersome to maintain.
- Do not use * and capture the element
You know the element you want to capture. So why do you use the wild card? If you are going to capture an input field, instead of using //*[@attritbute=’value’], use //input[@attritbute=’value’]. Why?
-
- First, you know the element you are going to capture and it is not going to add lots of effort to add the element type as you have inspected the element to find the XPATH.
- Since it is a wildcard, your XPath might not be unique. There can be UI framework-generated spans wrapped around the input field you have selected. In the below scenario, there are two elements, hence your test tends to cause unexpected issues.
<span attribute="element"> <input attribute="element"></span>
-
- It is also cumbersome for Selenium to locate elements as it has to traverse through every element. Hence you can experience a slowness during the execution.
- Use XPath axes to locate elements
Use of axes is encouraged compared to path expression as it is more stable and prone to fewer changes during a UI update. Let’s take an example:
<div attribute="name"> <span><label>Name</label> <span><p><input attribute="input"></span></p></div>
If you write the XPath using the expression for the input element:
//label[text()='Name']/../../span/p/input
Now due to a UI change if the p tag was removed, then your XPath fails. Your new XPath should be:
//label[text()='Name']/../../span/input
Now let’s try using axes to write an XPath:
//label[text()='Name']/ancestor::div/span/child::input
Conclusion
XPath plays a major role in software engineering. However, XPaths are mostly used in the test automation industry today. Hence, if you are an automation engineer or planning your career path as an automation engineer, XPath is a must-have skill 🤹♂️
It comes in three different flavors: absolute XPath, which is adding lots of maintenance over-head, relative XPath, which is commonly used in an automation project, and finally exact XPaths – the most powerful and efficient type.
These are some of the best practices I use to optimize the automation testbed when dealing with XPaths. Give it a try and share your thoughts and feedback 👇