First, you have to decide if you’ll use a CSS Selector or if you’ll use XPath. For the sake of this article, we’ll go straight to XPath. If we look a bit deeper into the code, we’ll see that this link is inside a <li> with an ID; we can use this to our advantage.
To select this, we could use something like:
//li[@id=’menu-item-14′]/a
In this case and on this site, this returns only one result, which is what we want, but something looks fishy to my eye. What if “menu-item-14” is a dynamic ID that changes when we reload the page or changes if the site creator decides to add another item to that menu?
What will happen is that our code will break, and we will have to fix it. That’s what’ll happen.
This means we need to find a more reliable way to find our element, so we’ll need to look even deeper in the code. If we look a tiny bit deeper, we’ll find that this <li> is inside a <ul> that has a unique ID, and that ID seems to be a static one that won’t change soon. This represents a much safer bet for our XPath to rely on.
If we use this as the start for our XPath, we will end with something like this:
//ul[@id=’top-menu’]/li/a
But wait, now we have another problem. This XPath will select all the links stored in this list, we need to narrow it down even more. For this,, we can follow two paths, either leave it as is and in the code handle the list of elements it returns, or we can be a bit more specific, so the XPath only returns one element.
From previous experience, I’ve noticed that being specific and introducing the complexity in the XPath saves time on the execution of it and also makes your test script a bit cleaner in the end since you won’t have to deal with the index later on.
Our final XPath expression to select this link would look like this:
//ul[@id=’top-menu’]/li/a[contains(text(), ‘Home’)]
So, question time. Why didn’t we ask for a link that contained that text from the beginning?
First, because that’s too generic of an expression. With an expression as simple as that, we expose ourselves to find more things than what we’re looking for.
Second, an expression like that one is not efficient. That expression forces Selenium to go and look through the whole DOM of the site to find all the possible matches.
XPath is a really powerful tool, but it can easily make your code a lot harder to read, slower, and more prone to breaking because if anything changes in the path you’re using for your search, the XPath will break. And not only will it break, but it won’t tell you which part of the XPath failed.
In conclusion, keep your XPath short, but not too short and specific enough to be able to resist slight changes in the DOM.
Mike Arias wrote this article.
Senior Software Testing Engineer of TechAID
Twitter: @theqaboy
Blog: qaboy.com/