Locators in Selenium: A Detailed Guide
By Shaumik Daityari, Community Contributor and Pradeep Krishnakumar, Manager - August 7, 2019
Over the past decade, Selenium has become the most popular option for developers to run automation tests for web applications. The Selenium suite has excellent flexibility — it allows teams to run the tests on a local machine or the cloud, interfacing through many commonly used programming languages. While there are a set of challenges in Selenium, but the flexibility that it provides makes Selenium the best testing framework to adopt. In this post, we explore how to use locators in Selenium.
What are Locators in Selenium?
Locators in Selenium were briefly described in our guide to getting started with the Selenium framework with Python. The broad steps to perform a test through Selenium are as follows –
- Download browser drivers
- Initiate a Selenium WebDriver
- Load web applications
- Perform designated actions in a defined test
- Assess if the test achieved the desired outcome
- Close the WebDriver
Locators in Selenium come into action in the fourth step above, after the Selenium WebDriver is initialized and loaded the webpage to be tested. A locator enables testers to select an HTML DOM element to act on. This post examines various types of locators in Selenium WebDriver.
The different locators in Selenium are as follows:
- By CSS ID: find_element_by_id
- By CSS class name: find_element_by_class_name
- By name attribute: find_element_by_name
- By DOM structure or xpath: find_element_by_xpath
- By link text: find_element_by_link_text
- By partial link text: find_element_by_partial_link_text
- By HTML tag name: find_element_by_tag_name
While all these locators return single elements, one may use the .find_elements() method to find multiple elements.
Locate Elements by CSS ID
This is by far the simplest method of locating an element. The CSS ID, stored in the id attribute of an HTML DOM element, is unique for every element in the page by design. Thus, an ID can uniquely identify an element.
To use this feature, one needs to call the .find_element_by_id() method of the webdriver class. Here is the usage for it.
from selenium import webdriver driver = webdriver.Chrome('./chromedriver') driver.get("https://www.python.org") search_bar = driver.find_element_by_id("id-search-field")
If there is no DOM element with the ID that one is searching for, a NoSuchElementException is raised, which one can account for, by using a try-catch block.
Theoretically, every DOM element on a page should have a unique ID. However, in real life, one does not commonly observe this. Most elements may not have an ID or may encounter two elements with the same ID. In such cases, one needs to use a different strategy to identify a DOM element uniquely.
Locate Elements by CSS Class
A second strategy of locating elements on a page is to search by the class name. The class name is stored in the class attribute of an HTML tag. By design, a CSS class applies to a group of DOM elements. The .find_element_by_class_name() method only returns the first element with the matching class. It raises a NoSuchElementException if there is no element with the given class name. Here is how to use the method in the driver.
from selenium import webdriver driver = webdriver.Chrome('./chromedriver') driver.get("https://www.python.org") # Returns first element with matching class first_search_bar = driver.find_element_by_class_name("id-class-name")
Locate Elements by Name
In HTML5, form elements often have a name attribute associated with them. The .find_element_by_name() method only returns the first element with the matching class. If there are multiple elements of the same name, the first matched element would be returned. No matching elements result in a NoSuchElementException error.
Consider the following form:
<form id="loginForm"> <input name="name" type="text" value="First Name" /> <input name="name" type="text" value="Last Name" /> <input name="email" type="text" value="Business Email" /> <input name="password" type="password" /> <input name="continue" type="submit" value="Sign Me Up" /> </form>
The following code returns the email form element.
email_input = driver.find_element_by_name("email")
However, the following code only returns the first name form element.
name_input = driver.find_element_by_name("name")
Using the .find_element_by_name() method, it is not possible to get to the last name input form field in the example. This brings us to the next locator.
Locate Elements by XPath
If one has failed to identify an element by ID, class or name, one would need to locate the element through its XML path. This process may also be implemented while reading an XML document. In this tutorial, we explore the use of relative paths, as absolute paths are prone to errors with the slightest change in the HTML structure.
We will use the .find_element_by_xpath() method to locate an appropriate element in the document. The argument that the .find_element_by_xpath() method takes is the path to the element.
To find the email input field in the above example of an HTML form, one may use the following code:
email_input = driver.find_element_by_xpath("//form[input/@name='email']")
This code snippet searches for the first form element of the page. Within this form, it searches for an input with the name which equals the value email, thus narrowing down to the required element.
Next, let us try to locate the first and last names input element of the form above.
first_name = driver.find_element_by_xpath("//form[@id='loginForm']/input") last_name = driver.find_element_by_xpath("//form[@id='loginForm']/input")
The method first searches for a form with the ID login form and then selects the first and second input elements of the form as the first and last names.
Other Single Element Locators
In addition to the popular methods that we have discussed, there are a few other element locators in the Selenium WebDriver that testers may wish to explore.
One can locate elements by their HTML tag name using the .find_element_by_tag_name() method.
page_heading = driver.find_element_by_tag_name('h1')
One can also search for a hyperlink element using the link text. One can either use the .find_element_by_link_text() method to search for the exact link’s text, or .find_element_by_partial_link_text() method to search for partial text.
# Exact Link Text click_here_link = driver.find_element_by_link_text('Click Here') # Partial Link Text click_here_link = driver.find_element_by_partial_link_text('Click')
Locate Multiple Elements
In this tutorial, we have discussed methods that locate only single elements. One may want to select a group of elements and then iterate through them. The .find_elements() method helps in finding multiple elements in the DOM structure.
Here are common examples of the usage of the .find_elements() method. To find all input elements of a form with ID loginForm, use the following snippet –
from selenium.webdriver.common.by import By all_inputs = driver.find_elements(By.XPATH, '//form[@id='loginForm']/input')
To locate all elements with a class name, use the following code –
from selenium.webdriver.common.by import By all_elements = driver.find_elements(By.CLASS_NAME, 'my-css-class')
In addition to this, the By class has the following attributes:
- By.ID: search using the CSS ID
- By.LINK_TEXT: search using exact link text
- By.PARTIAL_LINK_TEXT: search using partial link text
- By.NAME: search using the name attribute
- By.TAG_NAME: search using the HTML tag name
Final Thoughts on Locators in Selenium
With this, we come to the end of the tutorial on locators in Selenium using Python. We discussed a variety of approaches to select elements within an HTML page. We first looked at single element selectors and then moved on to multiple element selectors in the Selenium WebDriver.