If you’ve ever written Selenium automation for any website, you’ll have dived into the DOM and seen a plethora of nested elements, class names, and all the rest of it. You may find yourself struggling to choose the best locator for your automation as you want to ensure your automation will work long-term, with as little maintenance required. Having worked in this domain for a couple of years now, I have picked up a few tips for choosing great locators for your Selenium automation that I would like to share.
Avoid absolute Xpaths where possible#
Although there are a few exceptions, absolute Xpaths should be avoided. They are fragile - meaning they can break with even the slightest modification to the website - and have performance issues. For me Xpaths are only ever a last resort for when a suitable Class, ID or CSS Selector is not available.
A good example is if you have several containers on a page, all with
the same Class name. There is no easy way to distinguish them, other
than the fact you know which container is used for a particular piece
of functionality. You could create an Xpath such as
html/body/div/div[@class='container'], however if any of the
container’s parent elements change, or the order of the containers
change, the Xpath would break and would need to be rewritten. In this
case, it would be better to use a Class name or a CSS Selector, which
isn’t so dependent on its parent elements.
Wildcard CSS Selectors can be a life saver#
When it comes to writing Selenium automation, I don’t think CSS
Selectors get the love they deserve. You may be used to CSS Selectors
.class, and you could just find elements by ID
or Class Name, however there’s another great way to use them.
Consider a web application that is built using React. Elements inside that app typically have a randomised string at the end each class name, and these strings can change whenever a new build is deployed. This makes it incredibly difficult to automate and have reliable UI tests. With wildcard CSS Selectors, you can disregard that randomised string and pick elements using just the human-readable Class prefix.
For example, if you have a form with some buttons at the bottom, and
those buttons have the Class name
cancelButton_f23gfihq, you can get these elements with the CSS
^ inside the CSS Selectors above means “any class beginning
with…”. You can also use
*, meaning “any class that contains…”,
$, which means “any class that ends with…”. Super useful, eh?
It’s okay to loop over elements with the same locator#
Sometimes we are backed into a corner when we have elements with the same Class and with no ID. Earlier I mentioned that absolute Xpaths are not optimal at all, and there is a way around this. You can get all of the elements with the same locator, and then iterate over them to check for the attributes you are looking for. I’m going to use Python for this example, though the syntax is mostly the same in Java, C# and other languages.
# import selenium, webdriver etc... # create your webdriver up here, and navigate to your webpage... # the text of the button we want to click desired_button_text = "Shop" # get all of the elements with the class name 'topNavButton', and # store in a list to iterate over later nav_buttons = driver.find_elements_by_class_name("topNavButton") # iterate over the buttons, and compare the text of each button # to the text we are looking for. once found, click it and break # out of the loop for button in nav_buttons: if button.text == desired_button_text: button.click() break
The above code is reliable as we’re not using fragile Xpaths, it can be placed in a method and reused to handle different cases, and you’re in total control of which attributes you’re checking against. Be wary that if you have a lot of elements with the same Class or CSS Selector, there could be a performance hit as you iterate over the elements.
ID’s are the safest locators to use#
There’s no doubt that CSS Selectors are great, however ID’s are the safest and easiest locator types to use. ID’s are supposed to be unique in each page, so you shouldn’t have problems with your automation selecting the wrong element.
The only caveat is that ID’s are not typically created automatically; developers will need to add these in manually, and so you will have to get them added either by raising your own pull request, or by buying the developer a beer!
The world of web UI testing is huge; there are so many different technologies and ways of interacting with the elements you need. However it is important to write your automation in a way in which it won’t need to be rewritten on every change to the front-end, so that you can focus on writing even more tests.
That concludes this tutorial. If you have any questions, feel free to reach out to me via Twitter, and keep an eye open for my upcoming tutorials.