UI Tests ft. XPath
Well, this post starts off with the basics first, but it will coincide with the title towards the end. I will try to convince you to switch your element locating practice from ids, class names, tag names … to XPath and will explain how this technique helps us test more efficiently.
The prevalence practice of UI testing is using “id”s when locating an element. If there is no id attribute for the element, new preference would probably be “classname”, “text” or so…And yet, at desperate times, there comes XPath to the rescue.
By “rescue”, I do not mean it is the ultimate solution -not even close- but saves the day indeed. I have seen many testers use XPath finder tools, get the absolute path and place it into the element binder methods in their code. Yes! this is a bad practice… Makes XPath Evil?
Breaking Down The Bias “XPath is Evil.”
Making this a relatively better approach is quiet easy by eliminating as much node set as possible and narrowing down the path.
I open my Google Chrome browser and navigate to google.com. I use the following technique to get the XPath of “Search Google” button;
On Element -> Right Click -> Inspect ->Right Click on the highlighted area in the inspector -> Copy -> Copy XPath
And here is the xpath:
But I know the name attribute of the button -it is unique in this case- so Let’s rewrite this;
As you see, using unique identifiers of the element can be applied to XPath as well. This style of XPath constructing makes the UI test more reliable which affects the business as in terms of low cost, more value. But isn’t this just another way of locating an element with a name attribute? Yes, it is…
So What Is The Catch?
Let’s say there is a test scenario to be automated with the help of Selenium WebDriver API and the functionality under test is Google’s search feature on its main page. Our steps are below;
- I am on Google’s main page
- Enter a search for “test”
- Enter search button
Based on step definitions, I assume there will be a search box on Google’s main page along with a search button. My expectation is finding some button screaming “I am the search button, Click me!”.
And in reality, it is exactly how I assumed. So, I go ahead and locate the elements.
I have the following result by demonstrating different strategies to get the same job done.
Search Box Options
By Name = > $x(“//input[@name=’q’]”);
By Id = > $x(“//input[@id=’lst-ib’]”);
Selenium (name attribute)
By Name = > findElement(By.name(“q”));
By XPath = > findElement(By.XPath(“//input[@name=’q’]”));
Selenium (id attribute)
By Id = > findElement(By.id(“lst-ib”));
By XPath = > findElement(By.XPath(“//input[@id=’lst-ib’]”));
Search Button Options
Selenium By Name
By Name = > findElement(By.name(“btnK”));
By XPath = > findElement(By.XPath(“//input[@name=’btnK’]”));
So looks like we have a few not-so-fragile ways of locating search box and search button. But the problem starts with someone messing with the text of the Search Box by replacing the value attribute of the input to “I’m Feeling Lucky” and the same way around for “Feeling Lucky” button. The automated UI test will not fail since it does not care how the end user interacts with the system.
Element’s name-attribute’s value has not changed and the system still behaves as expected when clicked on this binded element; so-called search button.
Messed Up Google
Remember! The behavior has not been altered in no means but just the informative texts of the buttons replaced with each other. This situation obviously make the user click on the misleading button which takes the user to a lucky website.
A regular automated UI test simply cannot catch this scenario if element binding is done as above.
Search Button Options;
$x(“//input[@name=’btnK’ and @value=’Google Search’]”);
findElement(By.XPath(“//input[@name=’btnK’] and @value=’Google Search'”));
This approach helps us not only locate the button element directly but also check and confirm how a user interacts with it. If either of the values change by mistake then the test should fail. This technique simply covers both aspects.
UI testing should cover the behaviors of a system through the user’s eyes. In practice, I notice the testers focus on how a test should be coded only and neglect the user side of the story which could easily cause some serious damage. I encourage you to use XPath and potentiate your tests to support user experience as well.