Mastering Relative Locators in Selenium

Relative locators are one of the most powerful recent additions to the Selenium WebDriver API. Introduced in Selenium 4, relative locators allow you to locate elements based on their position relative to other elements on the page.

In this comprehensive guide, we will dive deep into relative locators in Selenium. You‘ll learn:

  • What are relative locators and how they work
  • The 5 relative locator methods – above(), below(), toLeftOf(), toRightOf(), near()
  • Using relative locators with Java Selenium bindings
  • Chaining multiple relative locators
  • Real-world examples and sample code snippets
  • Advantages and limitations of using relative locators
  • Best practices for using relative locators effectively

So let‘s get started!

What are Relative Locators in Selenium?

Selenium provides several locator strategies like ID, Class, Name, CSS Selector, XPath etc. to find elements on a web page. All these locator types require us to directly find the target element by some unique identifier.

Relative locators are different. As the name suggests, they allow locating an element based on its position relative to some other element on the page.

The WebDriver uses the JavaScript function getBoundingClientRect() behind the scenes to find the size and coordinates of elements on the page. This information is then utilized to locate other elements relative to the reference element.

Some common real-world use cases where relative locators shine:

  • Locating elements that dynamically change identifiers
  • Finding elements in a complex, nested DOM structure
  • Dealing with elements that lack unique identifiers

Overall, relative locators make scripts more resilient to changes in the application. They also reduce locator maintenance effort in rapidly evolving web apps.

The 5 Relative Locator Methods in Selenium

Selenium 4 introduces 5 relative locator strategies to locate nearby elements. Let‘s examine each of these locators.

above()

Finds element(s) vertically above the specified element.

Syntax:

above(WebElement element)
above(By locator) 

Example: Clicks button above the search box

WebElement searchBox = driver.findElement(By.id("search"));
WebElement submitButton = driver.findElement(RelativeLocator.with(By.tagName("button"))
                                  .above(searchBox));

submitButton.click();  

below()

Locates element(s) vertically below the specified element.

Syntax:

below(WebElement element)  
below(By locator)

Example: Clicks link below search box

WebElement searchBox = driver.findElement(By.id("search"));
WebElement forgotLink = driver.findElement(RelativeLocator.with(By.partialLinkText("Forgot"))
                                 .below(searchBox));

forgotLink.click();

toLeftOf()

Finds element(s) horizontally to the left of specified element.

Syntax:

toLeftOf(WebElement element)
toLeftOf(By locator)

Example: Finds cart icon left of search box

WebElement searchIcon = driver.findElement(By.cssSelector(".search-icon"));
WebElement cartIcon = driver.findElement(RelativeLocator.with(By.className("fa-shopping-cart"))
                                  .toLeftOf(searchIcon));

String cartText = cartIcon.getText();

toRightOf()

Locates elements horizontally right of the specified element.

Syntax:

toRightOf(WebElement element)
toRightOf(By locator)

Example: Clicks language selector to right of search box

WebElement searchBox = driver.findElement(By.name("search")); 
WebElement langMenu = driver.findElement(RelativeLocator.with(By.tagName("select"))
                                 .toRightOf(searchBox));

langMenu.click();

near()

Finds element around 50 pixels (default) from specified element. Custom distance can also be set.

Syntax:

near(WebElement element)   
near(By locator)

near(WebElement element, int px)    
near(By locator, int px) 

Example: Finds and clicks the search button near the search text box

WebElement searchBox = driver.findElement(By.id("searchBox"));
WebElement searchBtn = driver.findElement(RelativeLocator.with(By.tagName("button"))
                                .near(searchBox));

searchBtn.click();                         

This covers the 5 relative locator methods provided by Selenium. Now let‘s see them in action with some end-to-end examples.

Using Relative Locators in Selenium with Java

Let‘s walk through a Selenium Java test script to demonstrate practical usage of relative locators.

We will automate a simple login flow on a demo site. The script will:

  1. Enter username
  2. Enter password
  3. Click Login button

Here‘s the site markup:

<input type="text" id="username"> 

<input type="password" id="password">

<button>Login</button> 

And here is how the script looks using standard locators:

WebElement username = driver.findElement(By.id("username"));
username.sendKeys("johnwick");

WebElement password = driver.findElement(By.id("password"));
password.sendKeys("wick1234");  

WebElement loginBtn = driver.findElement(By.xpath("//button[text()=‘Login‘]")); 
loginBtn.click();

This works fine. But now assume the application evolves and the login button loses its text. Our XPath won‘t work anymore.

This is where relative locators come in handy. We can rewrite the last part using below() instead:

WebElement password = driver.findElement(By.id("password"));

WebElement loginBtn = driver.findElement(RelativeLocator.with(By.tagName("button"))
                                                 .below(password));
loginBtn.click();                                                  

Our script is now more resistant to changes in the button text or attributes.

Let‘s look at another example using toRightOf():

WebElement username = driver.findElement(By.id("username"));

WebElement passwordIcon = driver.findElement(RelativeLocator.with(By.className("key-icon"))
                                                  .toRightOf(username));

Assert.assertEquals(passwordIcon.getCssValue("background-image"), "url(‘/images/key.png‘)");   

Here we avoided crafting a complex CSS selector to directly target the password icon. Much simpler with relative locators!

As you can see, relative locators simplify scripts and improve reliability.

Tips for Using Relative Locators

Here are some tips to use relative locators effectively:

Combine with other locators

Use ID, CSS Selector etc. to find the reference element. Then apply relative locator to locate the target element:

driver.findElement(RelativeLocator.with(By.tagName("button")).toRightOf(driver.findElement(By.id("username")))); 

Unique reference elements

Use reference elements that have unique locators like ID or CSS Selector. Avoid general tags like div, span etc.

Chaining

Chain multiple relative locators like below().toRightOf() when single locator is not enough.

Granular test methods

In Page Object Model, create separate methods for elements located with relative locators. This improves maintainability.

Fallback locators

Use relative locators as fallback instead of primary mechanism. Have a non-relative locator ready if needed.

Chaining Multiple Relative Locators

In some cases, finding an element requires using multiple relative locators sequentially. This is called chaining.

For example, consider the following markup:

<button>Prev</button>

<div class="post">
  ...
</div>

<button>Next</button> 

Let‘s say we want to click the "Next" button. Using a single relative locator won‘t help since both buttons have the same tag.

But we can chain below() and toRightOf() instead:

WebElement post = driver.findElement(By.className("post"));  

WebElement nextButton = driver.findElement(RelativeLocator.with(By.tagName("button"))
                                                         .below(post)
                                                         .toRightOf(post));

nextButton.click();   

This first finds the button below the post, then picks the one towards right of post.

Chaining enables locating elements irrespective of the complexity of page layouts.

Key Advantages of Using Relative Locators

Let‘s summarize some of the notable advantages of using relative locators:

Readability

Relative locators use simple language like above, near, left making scripts self-documenting.

Robustness

Changes in attribute values won‘t break tests relying on relative positions.

Maintenance

No need to constantly update complex custom XPath/CSS locators.

Finds dynamic elements

Can locate elements lacking identifiers using context from other elements.

Support nested DOM

Chaining helps interact with elements in complex nested structures.

Platform/browser independence

Relative locators behave reliably across browsers and environments.

Limitations of Relative Locators

However, relative locators also come with a few limitations:

  • Browser window size changes may cause elements to shift position and overlap

  • Performance overhead due to additional computations

  • Need other elements to be visible for locating hidden elements

  • Can fail for frequently and drastically changing dynamic UIs

  • May require tweaking when page layout is altered

So while relative locators make scripts more resilient, some care is still needed to handle edge cases.

Best Practices For Using Relative Locators

Follow these best practices to use relative locators effectively:

  • Prefer reference elements closer to target element – Minimizes risk of overlapping during position shifts

  • Fall back to standard locators – Have alternate CSS/XPath locators ready

  • Assert relative positions – Detect layout changes breaking relative locator

  • Granular page object models – Keep methods using relative locators independent

  • Cross-browser testing – Account for subtle rendering differences across browsers

  • Retry on failure – Retry relative locators before failing tests

Conclusion

Relative locators are a game changer for writing reliable, cross-browser automated tests. They make scripts more resilient to application changes and also improve locator maintainability.

However, they have some limitations around element overlap and dynamic UIs. Following best practices around chaining, robust fallback locators, asserting relative positions etc. can help address these gaps.

Overall, when used judiciously, relative locators take Selenium test automation to the next level. They encourage and facilitate designing tests based on pages rather than individual elements.

So do explore relative locators for your next test automation effort. And let me know if you have any other tips or tricks for mastering relative locators!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts