Chapter{4}: Selenium Automation Testing: Mastering XPath: Advanced Techniques Made Simple
Alright, so you’ve got the basics of XPath down — absolute vs. relative, contains()
, starts-with()
, and so on. But what if you're working on a real-world website like Myntra, where elements aren't always neatly structured? Let's level up your XPath skills so you can handle anything that comes your way!
1. When to Use Which XPath?
Not all XPaths are created equal. Some are better for stability, some for flexibility. Here’s a simple guide:
Use Absolute XPath (/
) only if the page structure is static (rare).
- Avoid it when dealing with dynamic elements (which is most of the time).
Use Relative XPath (//
) for almost everything—it’s flexible and resistant to small changes in the page layout.
- Use
contains()
when part of an attribute is stable but the full value changes (like IDs that have random numbers). - Use
starts-with()
when you know the beginning of an attribute but not the end. - Use
text()
when the visible text is the only reliable way to find an element.
2. Examples from a Web page(let’s say Myntra).
Finding a Search Bar
Let’s say the search bar has a class that looks like this:
<input type="text" class="desktop-searchBar">
You can locate it using:
driver.findElement(By.xpath("//input[@class='desktop-searchBar']")).sendKeys("Shoes");
Great! But what if tomorrow, the class name changes slightly?
Better way using contains()
:
driver.findElement(By.xpath("//input[contains(@class, 'searchBar')]")).sendKeys("Shoes");
This works even if they rename the class to myntra-searchBar
or desktop-searchBar-new
.
3. Handling Buttons with Dynamic Text
Imagine the “Add to Cart” button changes from “Add to Cart” to “Added!” after clicking.
<button class="cart-btn">Add to Cart</button>
Find the button using text()
:
driver.findElement(By.xpath("//button[text()='Add to Cart']")).click();
This will fail after clicking because the text changes.
Better approach: Use contains(text(), 'Add')
, which works for both "Add to Cart" and "Added!":
driver.findElement(By.xpath("//button[contains(text(), 'Add')]")).click();
4. Traversing the DOM Like a Pro
Parent to Child Navigation
If you have this structure:
<div class="product">
<h2>Men's Shoes</h2>
<button class="buy-now">Buy Now</button>
</div>
You can select the “Buy Now” button based on its parent:
driver.findElement(By.xpath("//div[@class='product']/button")).click();
This selects the button inside .product
.
Child to Parent Navigation (..
)
Need to go up instead? Use ..
to move to the parent. If you locate the button first but need to find the product name:
driver.findElement(By.xpath("//button[@class='buy-now']/..//h2")).getText();
This finds the parent div
of the button and then locates the h2
inside it.
5. Working with Siblings
If you need to select a product price next to a title:
<div class="product">
<h2>Men's Shoes</h2>
<span class="price">₹1999</span>
</div>
You can use XPath to jump to the price:
driver.findElement(By.xpath("//h2[text()='Men's Shoes']/following-sibling::span")).getText();
This finds the h2
and then moves to its next sibling.
6. Using *
When You're Unsure
Sometimes, the tag might change from <button>
to <a>
. Instead of guessing, use *
to match any tag:
driver.findElement(By.xpath("//*[contains(text(), 'Add to Cart')]")).click();
This works for any element (<button>
, <a>
, <span>
, etc.) as long as the text remains.
7. When to Avoid XPath?
- If an element has a unique ID, prefer
By.id()
over XPath. - If it has a stable name,
By.name()
is usually faster. - XPath can be slower than CSS selectors. If performance is an issue, use:
driver.findElement(By.cssSelector("button.cart-btn")).click();
- instead of
driver.findElement(By.xpath("//button[@class='cart-btn']")).click();
When dealing with dynamic elements on a webpage, some attributes stay the same, while others change frequently due to factors like session-based IDs, randomized class names, or dynamically generated content.
1. Attributes That Usually Change (Dynamic)
These attributes often get modified every time the page is loaded or interacted with:
- ID (
id
) → Many modern websites generate unique IDs dynamically (e.g.,button-12345
vs.button-67890
on the next load). - Class (
class
) → Sometimes classes have dynamically generated parts (e.g.,btn-x345
today andbtn-y678
tomorrow). - Name (
name
) → In rare cases, names can be generated dynamically, especially in form inputs. - Href (
href
) → URLs may have session tokens or timestamps (e.g.,https://myntra.com/product/xyz?session=12345
). - Data Attributes (
data-*
) → Some sites usedata-id
,data-product
, or similar attributes that change dynamically. - Text Content (
text()
) → Button text might change after interaction (e.g., "Add to Cart" → "Added!").
2. Attributes That Usually Stay the Same (Stable)
These attributes tend to remain unchanged and are good candidates for XPath selection:
- Tag Name (
input
,button
,div
,a
) → A button will likely stay a button. - Aria Labels (
aria-label
) → Accessibility labels usually remain constant. - Placeholder (
placeholder
) → Input fields often retain the same placeholder text. - Role (
role
) → Elements with specific functions (likerole="button"
) usually don't change. - Partial Class Names (
class
) → If only part of a class is dynamic, you can usecontains()
in XPath.
Final Thoughts
XPath is super powerful, but knowing when and how to use it is key. Use relative XPath as much as possible, mix in functions like contains()
and starts-with()
, and traverse the DOM smartly. Now go forth and automate like a pro!
You can now catch the podcast on YouTube too!
.
.
.
Happy Coding!