Locators and XPath

Which locators does Selenium support and which do you prefer?

Eight By strategies: id, name, className, tagName, linkText, partialLinkText, cssSelector, xpath, plus Selenium 4 relative locators.

Preference order: id (or a data-testid) → name → short CSS selector → XPath when you need text or to move up the DOM. Avoid absolute XPath and generated class names.

What is the difference between absolute and relative XPath?

AbsoluteRelative
starts at the root with a single slash: /html/body/div[2]/form/input[1]starts anywhere with //: //input[@id='email']
breaks when any parent element changesstable as long as the element's attributes stay
never use in a frameworkalways use

How do you write an XPath for a dynamic element whose id changes?

<button id="btn-addcart-83721" class="btn add-cart">Add to Cart</button>
By.xpath("//button[starts-with(@id,'btn-addcart-')]")
By.xpath("//button[contains(@class,'add-cart')]")
By.xpath("//button[normalize-space()='Add to Cart']")
By.cssSelector("button[id^='btn-addcart-']")          // CSS: ^= starts with, $= ends with, *= contains

Use the stable part of the attribute, the visible text, or a stable parent.

Explain XPath axes with an example.

Axes move from a known element to a related one. Classic case: click "Remove" in the cart row whose product name is known.

<tr><td class="name">Boat Rockerz 450</td><td>₹1,499</td><td><button>Remove</button></td></tr>
// from the name cell, go to the following sibling cell that has the button
By.xpath("//td[text()='Boat Rockerz 450']/following-sibling::td/button")
// or up to the row, then down
By.xpath("//td[text()='Boat Rockerz 450']/ancestor::tr//button[text()='Remove']")
By.xpath("//button[text()='Remove']/parent::td")

Common axes: parent, child, ancestor, descendant, following-sibling, preceding-sibling, following, preceding.

What is the difference between findElement and findElements?

findElementfindElements
returns one WebElement (the first match)returns List<WebElement>
throws NoSuchElementException if nonereturns an empty list if none
waits up to the implicit waitalso waits up to the implicit wait (then returns empty)
boolean errorShown = !driver.findElements(By.cssSelector(".error-message")).isEmpty();

Tip: Use findElements(...).isEmpty() to check that something is not present without a try/catch.