Selenium Locators Practice
Locators are the foundation of every Selenium test — a flaky locator makes a flaky test. This page gives you 150+ locator exercises, organized from single locators to XPath axes and framework-level tasks, plus worked solutions on a sample page so you can check your answers.
New to locators? Read Selenium Locators and XPath first, and keep the Selenium Locators Cheat Sheet open. Test any selector instantly in the CSS & XPath Selector Playground.
How to Practice
- Open the page in Chrome and press F12.
- In the Elements panel, press Ctrl+F (Cmd+F on Mac) and type a CSS selector or XPath — Chrome highlights the matches and shows a count like "1 of 1".
- Aim for exactly one match. "1 of 3" means your locator is too broad.
- Only then put it in code:
driver.findElement(By.xpath("…")).
Worked Example: A Sample Page With Solutions
Use this small page to practice. Save it as locators.html and open it in your browser, or paste it into the Selector Playground. Notice the dynamic IDs (user-7f3a, pass-9c1d) — in real apps these change on every build.
<form id="loginForm">
<label for="user-7f3a">Username</label>
<input id="user-7f3a" name="username" class="form-control input-lg" type="text" placeholder="Enter username">
<label for="pass-9c1d">Password</label>
<input id="pass-9c1d" name="password" class="form-control" type="password">
<input id="remember" name="remember" type="checkbox">
<label for="remember">Remember me</label>
<button type="submit" class="btn btn-primary" data-testid="login-btn">Log in</button>
<a href="/forgot-password">Forgot password?</a>
</form>
<table id="users">
<tr><th>Name</th><th>Role</th><th>Action</th></tr>
<tr><td>Asha</td><td>Admin</td><td><input type="checkbox"> <button>Edit</button></td></tr>
<tr><td>Ravi</td><td>Tester</td><td><input type="checkbox"> <button>Edit</button></td></tr>
</table>
Basic locator solutions
| Task | Solution | Why |
|---|---|---|
| Remember-me checkbox by ID | By.id("remember") |
Stable, unique ID — the best locator when available |
| Username by name | By.name("username") |
The ID is dynamic, but the name is stable |
| Login button by class | By.className("btn-primary") |
By.className("btn btn-primary") fails — compound class names aren't allowed |
| Count all inputs | driver.findElements(By.tagName("input")).size() → 5 |
Includes the two table checkboxes |
| Forgot-password link | By.linkText("Forgot password?") |
Exact, case-sensitive text |
| Same link, partial text | By.partialLinkText("Forgot") |
Survives small wording changes |
CSS selector solutions
| Task | CSS selector |
|---|---|
| tag#id | input#remember |
| Multiple classes | button.btn.btn-primary |
| Test ID attribute ⭐ | [data-testid='login-btn'] |
| Dynamic ID — starts with | input[id^='user-'] |
| Ends with | input[name$='word'] |
| Contains | a[href*='forgot'] |
| Direct child | form#loginForm > button |
| Descendant (matches 3) | #loginForm input |
| Ravi's role cell | table#users tr:nth-child(3) td:nth-child(2) |
XPath function and operator solutions
| Task | XPath |
|---|---|
Dynamic ID with starts-with() |
//input[starts-with(@id,'user-')] |
| Exact text | //button[text()='Log in'] |
| Text with stray spaces | //button[normalize-space()='Log in'] |
Partial text with contains() |
//a[contains(text(),'Forgot')] |
| AND | //input[@type='password' and @name='password'] |
| OR (optional attribute) | //input[@name='username' or @name='email'] |
| Second of several matches | (//button[text()='Edit'])[2] |
XPath axes solutions ⭐
| Task | XPath | Finds |
|---|---|---|
| Input after a label (following-sibling) | //label[text()='Password']/following-sibling::input[1] |
Password field |
Input linked to a label's for |
//input[@id=//label[text()='Password']/@for] |
Password field |
| Checkbox before a label (preceding-sibling) | //label[text()='Remember me']/preceding-sibling::input[1] |
Remember-me checkbox |
| Cell next to a known cell | //td[text()='Ravi']/following-sibling::td[1] |
"Tester" |
| Cell before a known cell | //td[text()='Tester']/preceding-sibling::td |
"Ravi" |
| Checkbox in Ravi's row | //td[text()='Ravi']/following-sibling::td//input[@type='checkbox'] |
Row checkbox |
| Button in Ravi's row (parent) | //td[text()='Ravi']/parent::tr//button |
Ravi's Edit button |
| Role of the row containing "Asha" | //table[@id='users']//tr[td[text()='Asha']]/td[2] |
"Admin" |
| Table containing a button (ancestor) | //button[text()='Edit']/ancestor::table |
The users table |
The "row containing X" patterns are what interviewers mean by dynamic table handling: you find the row by a value you know, then move to the cell you need — no fixed row numbers.
Which Locator Should You Choose?
- ID — if it's unique and not auto-generated.
- A dedicated test attribute like
data-testid— ask developers to add these; they survive redesigns. - Name — good for form fields.
- CSS selector — fast, readable, great for attributes and classes.
- Relative XPath — when you need text or to move between elements (axes).
- Never absolute XPath (
/html/body/div[2]/…) — it breaks when any wrapper element changes. See Absolute vs Relative XPath.
Level 1 — Basic Locator Practice
Master every locator individually before moving to CSS and XPath.
ID Locator
- Locate the username, password and login button using ID.
- Validate element presence using ID.
- Locate an element whose ID is not unique and observe which one Selenium returns.
Name Locator
- Locate an input, a radio button, a checkbox and a submit button using Name.
- Handle multiple elements sharing the same Name attribute.
ClassName Locator
- Locate an element using a single class.
- Try an element with multiple classes, observe the failure, then fix it by selecting one class.
- Identify classes reused across pages, and list the limitations of ClassName.
TagName Locator
- Locate all input elements; count all links and all buttons on a page.
- Iterate through elements found by TagName and extract the text from all labels.
LinkText and PartialLinkText
- Click Login, Register and Forgot Password using full LinkText, and verify navigation.
- Test that LinkText is case-sensitive, and handle a link whose text changes.
- Locate links with PartialLinkText, handle dynamic link text, and compare the two approaches.
Level 2 — CSS Selector Exercises
Basic CSS
-
Use
tag#id,tag.class, multiple classes, an attribute selector, and an attribute with a value. You may also find CSS Selectors in Selenium useful.
Advanced CSS
- Use starts-with (
^=), ends-with ($=) and contains (*=). - Use the child (
>) and descendant (space) selectors, and:nth-child().
Real-Time CSS Scenarios
- Convert an XPath to a CSS selector; choose CSS over XPath and justify the decision.
- Fix a broken CSS locator and handle dynamic attributes with CSS.
Level 3 — XPath Exercises
Absolute vs Relative XPath
- Create an absolute and a relative XPath for the Login button.
- Change the page structure, observe the absolute XPath fail, then fix it.
- Explain which XPath style your project uses, and why.
XPath Functions
- Use
contains(),starts-with(),text()andnormalize-space(). - Handle dynamic text and fix a flaky XPath.
XPath Operators
- Use AND and OR; combine multiple attributes; handle optional attributes; confirm exactly one match.
XPath Axes (most important)
- Use parent, child, following, preceding, following-sibling, preceding-sibling and ancestor.
- Handle table rows and columns, dynamic lists and nested elements.
Level 4 — Real-Time Application Scenarios
Login Page
- Locate a username with a dynamic ID, a password without ID or name, and the login button by its text.
- Locate elements relative to their labels, and locate the error message after a failed login.
Dynamic Elements
- Handle dynamic IDs, dynamic class names and auto-generated attributes.
- Identify the stable attributes and write future-proof locators.
UI Change Scenarios
- Fix locators broken by a UI change, a text change, or an extra wrapper
div. - Refine a locator after duplicate elements appear, and simplify an overly long XPath.
Level 5 — Framework-Level Exercises
- Store locators in a Page Object as
Byfields, and refactor duplicate locators. - Apply a naming convention (e.g.
loginButton,usernameInput). - Debug a locator failure from logs and a saved page source.
- Review a teammate's locators and suggest improvements.
See Selenium Frameworks & Page Object Model.
Interview Capstone Tasks
- Automate a login using the best locator strategy, and justify each choice.
- Identify and replace weak locators in an existing test.
- Convert an absolute XPath to a relative one, and an XPath to CSS.
- Explain a fallback locator strategy.
- Debug a NoSuchElementException and handle a StaleElementReferenceException.
- Design the locator strategy for an entire page.
Best Demo Websites for Locator Practice
| Site | Best for |
|---|---|
| NavTutorial Practice Hub — Demo Elements | Every element type in one place: forms, tables, dynamic elements |
| SauceDemo (saucedemo.com) | Login page, ID/name/class, product lists |
| OrangeHRM demo (opensource-demo.orangehrmlive.com) | Enterprise UI, dynamic attributes, advanced XPath |
| Rahul Shetty Academy practice page (rahulshettyacademy.com/AutomationPractice/) | XPath axes, tables, checkboxes |
| DemoQA (demoqa.com) | Dynamic elements, nested DOM, modern UI |
| The Internet (the-internet.herokuapp.com) | LinkText, dynamic content, tables, frames |
(The old automationpractice.com store is no longer available — use the sites above instead.)
Site-Mapped Practice Exercises
SauceDemo — Login
- Locate username, password and login button by ID; username by name; login button by class.
- Locate all inputs by tag name; the login button by CSS and by XPath.
- Break the ID locator and fix it with XPath; explain why ID is best here.
OrangeHRM — Dynamic Attributes and XPath Functions
- Locate the username without its ID; handle changing attribute values.
- Use
contains(),starts-with()andtext(); locate fields by their label text. - Use AND and OR conditions; fix locators that break after a refresh; write reusable XPath.
DemoQA — Absolute vs Relative XPath
- Create an absolute XPath for the Submit button and run the test.
- Change the DOM, observe the failure, create a relative XPath, and compare stability.
The Internet — LinkText
- Locate the "Form Authentication" link with LinkText, then with PartialLinkText ("Authentication").
- Imagine the text changes: observe the failure, fix it with XPath, and decide on the best locator.
Rahul Shetty — CSS and XPath Axes
- Select checkboxes with CSS attribute, contains, child and descendant selectors; compare with XPath.
- Practice parent, child, following, preceding, sibling and ancestor axes on the tables.
- Locate a checkbox relative to its text, and explain your approach as you would in an interview.
Framework-Level Practice
-
On SauceDemo or OrangeHRM, store locators in page objects, name them clearly, remove duplicates, and review a teammate's strategy.
Common Locator Mistakes
- Copying the XPath from DevTools — "Copy XPath" often gives brittle, index-based paths. Write your own.
- Relying on auto-generated IDs like
user-7f3a— usestarts-with, a name, or adata-testid. - Matching more than one element — Selenium silently uses the first, which may be hidden.
- Using text that changes with language or content updates — prefer attributes when you can.
- Forgetting iframes — a correct locator still fails if the element is inside a frame you haven't switched to.
From Real Projects
Writing locators was a daily task in my automation work — identifying elements by id and class name, and writing XPath when those weren't available or unique. On Canolog, a dealership management system with many similar-looking forms and tables across sales, inventory and service, a precise, readable locator mattered: it had to find exactly one element and survive small layout changes. Every locator went into a POM class and was checked during script reviews. Practice these exercises until writing a stable XPath takes seconds.
📚 Official documentation: Selenium docs: Locator strategies · Selenium documentation
FAQs
What order should I practice Selenium locators in?
Basic locators → CSS selectors → XPath functions → XPath operators → XPath axes → real-time scenarios → framework-level tasks → interview capstone.
Why should I intentionally break locators?
Breaking locators shows you how they fail, which builds the debugging skills you need in real projects and interviews.
Which is faster, CSS or XPath?
In modern browsers the difference is usually negligible. Choose for readability and stability: CSS for attributes and classes, XPath when you need text or to navigate between elements.
How do I handle dynamic IDs?
Use the stable part with starts-with() or CSS ^=, switch to another stable attribute such as name or data-testid, or locate the element relative to its label.
Which website is best for XPath axes?
The Rahul Shetty Academy practice page has good tables and checkboxes for parent, sibling, following and preceding axes — and the sample page above has worked solutions.
What is the final interview-level exercise?
Design a complete locator strategy for an entire page: primary locators, fallbacks, and a justification for each.