Locators in Selenium are commands that identify specific elements on a web page during automated testing. They enable scripts to interact with buttons, inputs, and other UI components by matching them to their unique attributes in the HTML structure.
Selenium uses locators to find and manipulate elements in a browser. Without them, automated tests cannot click, type into, or verify content on a webpage. Each locator strategy targets a different attribute-like ID, class name, or XPath-to pinpoint an element accurately.
The most common strategies include ID, name, class name, tag name, link text, partial link text, CSS selector, and XPath. Each has strengths depending on the page's structure and stability. For example, IDs are unique and fast to match, while XPath offers useful flexibility for complex selections.
Selenium sends a command to the browser's DOM (Document Object Model) using a specified locator. The browser searches the HTML tree for an element that matches the criteria. Once found, Selenium performs actions like clicking, typing, or retrieving text.
For instance, if a test needs to enter a username into a field, the script uses a locator like By.id("username") to find the input element. The WebDriver then sends keystrokes to that specific field.
Locators are written in code using methods from the Selenium WebDriver API. In Java, you'd use driver.findElement(By.id("login-button")). In Python, it's driver.find_element(By.ID, "submit"). The syntax varies by language, but the underlying logic remains consistent.
Each locator type serves a different purpose based on the HTML structure. The choice affects reliability, speed, and maintainability.
| Locator Type | When to Use | Example | Reliability |
|---|---|---|---|
| ID | Elements with unique IDs | By.id("submit-btn") |
High - IDs are meant to be unique |
| Name | Inputs with a 'name' attribute | By.name("email") |
Moderate - may not be unique |
| Class Name | Elements with class attributes | By.className("btn-primary") |
Low - classes often reused |
| CSS Selector | Flexible targeting with syntax similar to CSS | By.cssSelector("input[name='password']") |
High - fast and widely supported |
| XPath | Complex or changing structures | By.xpath("//button[text()='Submit']") |
Variable - useful but slower |
Use IDs when available-they're the fastest and most stable. CSS selectors are preferred over XPath for performance and readability. XPath shines when you need to locate elements based on text content or parent-child relationships.
A common mistake is relying on relative XPath like //div[3]/button. These fail when layout changes. Instead, use absolute paths only when necessary, and prefer //button[text()='Save'] or //input[@id='save'].
I automated a login flow on a staging site using locators. The login form had:
id="email"name="password"class="btn btn-success"Using Python and Selenium WebDriver, I wrote:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://test-site.example/login")
# Find and fill email
email_field = driver.find_element(By.ID, "email")
email_field.send_keys("[email protected]")
# Find and fill password
password_field = driver.find_element(By.NAME, "password")
password_field.send_keys("secret123")
# Click submit
submit_button = driver.find_element(By.CLASS_NAME, "btn-success")
submit_button.click()
# Verify success
assert "dashboard" in driver.current_url
This script passed reliably because each locator targeted a stable attribute. Changing the class name or adding extra divs didn't break it.
When I tried using By.tagName("button") instead, the test failed. There were multiple buttons on the page. The locator matched the first one, which wasn't the submit button.
Many assume that XPath is always better than CSS selectors. That's false. CSS selectors are faster and simpler for most cases. According to the Selenium documentation, CSS selectors are compiled into native JavaScript queries, making them quicker than XPath in most browsers.
Another myth: "XPath is more precise." While XPath supports complex expressions, overusing it leads to brittle tests. A well-written CSS selector like input[type='submit'][value='Login'] is clearer and faster than //input[@type='submit' and @value='Login'].
Some teams use By.linkText() for navigation links. But if the text changes (e.g., "Sign In" becomes "Log In"), the test breaks. Use By.partialLinkText() or rely on IDs instead.
Always validate locators before running full test suites. Tools like Chrome DevTools allow you to test selectors in the console. Run document.querySelector("#username") to confirm an element exists before writing code.
Choose locators based on uniqueness and stability. Prioritize ID, then name, then CSS selectors. Avoid XPath unless you need advanced logic.
Never hardcode values. Use variables or configuration files for expected text or URLs. This makes tests easier to update.
When elements load dynamically, wait for them to appear. Use explicit waits like WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "submit"))) to avoid timing issues.
Test locators independently. Write small scripts to verify each one works before integrating into a larger set. This isolates failures early.
Remember: a locator is only as good as the HTML it references. If the page changes, the test fails. Maintain locators through version control and review them during code audits.