Selenium Locator Strategies
| Locator Strategy | Syntax | Best Used When |
| id | By.id("username") |
The element has a unique ID (fastest and preferred) |
| name | By.name("email") |
The element has a unique name attribute |
| className | By.className("btn-primary") |
A single unique CSS class identifies the element |
| tagName | By.tagName("a") |
Selecting multiple elements of the same tag |
| linkText | By.linkText("Sign In") |
Selecting hyperlinks using exact visible text |
| partialLinkText | By.partialLinkText("Sign") |
Selecting hyperlinks using partial visible text |
| cssSelector | By.cssSelector("#login .btn") |
Fast, concise, and commonly preferred after id |
| xpath | By.xpath("//input[@id='user']") |
Powerful locator supporting text matching and DOM traversal |
Recommended Locator Priority
id → name → cssSelector → xpath
Use XPath only when advanced navigation, relationship-based locating, or text matching is required.
XPath Syntax
| XPath Pattern | Example |
| Absolute XPath | /html/body/div[1]/form/input |
| Relative XPath (recommended) | //input[@id='user'] |
| Attribute Match | //input[@name='email'] |
| Multiple Attributes | //input[@type='text' and @name='user'] |
| Text Match | //button[text()='Submit'] |
contains() |
//div[contains(@class,'error')] |
starts-with() |
//input[starts-with(@id,'user_')] |
| Index | //table//tr[2]/td[3] |
| Any Element | //*[@id='main'] |
Best Practice: Prefer Relative XPath because it is more maintainable and less brittle than Absolute XPath.
Advertisement
XPath Axes ⭐
XPath Axes allow navigation based on relationships between elements.
| Axis | Family Analogy |
child:: |
Your children |
parent:: |
Your parents |
following-sibling:: |
Younger siblings |
preceding-sibling:: |
Elder siblings |
ancestor:: |
Grandparents |
descendant:: |
Grandchildren |
self:: |
Yourself |
following:: |
Any element after you |
preceding:: |
Any element before you |
Example
//td[text()='John']/ancestor::tr/following-sibling::td
This navigates from a known table cell to another related cell using XPath relationships.
CSS Selectors
| CSS Pattern | Example |
| ID | #username |
| Class | .btn-primary |
| Tag + Class | input.form-control |
| Attribute | input[name='email'] |
| Contains | div[class*='error'] |
| Starts With | input[id^='user_'] |
| Ends With | input[id$='_name'] |
| Child Selector | #form > input |
| Descendant Selector | #form input |
nth-child() |
li:nth-child(2) |
CSS Limitation: CSS Selectors cannot navigate upward to parent elements. When parent or ancestor traversal is required, use XPath.
Dynamic Elements ⭐
When element IDs or attributes change dynamically between executions, use stable locator strategies.
Partial Attribute Match
//input[contains(@id,'user')]
//div[starts-with(@id,'msg_')]
Anchor to Nearby Stable Text
//label[text()='Email']/following-sibling::input
Anchor to a Stable Parent
//div[@id='login-form']//input[@type='text']
findElement() vs findElements()
| Feature | findElement() |
findElements() |
| Returns | Single WebElement |
List<WebElement> |
| When No Match Exists | Throws NoSuchElementException |
Returns an empty list |
| Typical Usage | Locate a single element | Locate multiple elements for counting or iteration |
Example
int totalLinks = driver.findElements(By.tagName("a")).size();
This returns the total number of hyperlinks on the current page.
Go Deeper
Continue learning with: