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> that has 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 1 result which is what we want, but something looks fishy to my eye. What if “menu-item-14” is a dynamic ID and changes when we reload the page or changes if the creator of the site 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, for this 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 in the near future. 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 2 paths, we can 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 index later on.
Our final XPath expression to select this link would look like:
//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 actually 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, a lot 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 it will break, 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.
This article was written by Mike Arias
Senior Software Testing Engineer of TechAID
Twitter: @theqaboy
Blog: qaboy.com/