The Agile Way

The Agile Way

Share this post

The Agile Way
The Agile Way
Case Study: Locator Chaining in Selenium WebDriver

Case Study: Locator Chaining in Selenium WebDriver

Cleaner and more readable locators in Selenium tests with Locator Chaining

Courtney Zhan's avatar
Zhimin Zhan's avatar
Courtney Zhan
and
Zhimin Zhan
Jan 16, 2023
∙ Paid
1

Share this post

The Agile Way
The Agile Way
Case Study: Locator Chaining in Selenium WebDriver
Share

Locator Chaining, in test automation, is a way to find an element relative to another. I will illustrate how to use locator chaining with a real example in this article.

Table of Contents:
· One Selenium Test Failed
· Analyse
· The Problem — Multiple Elements
· The Solution — Locator Chaining
∘ 1. Find all matching elements
∘ 2. Filter for displayed elements
∘ 3. Get the first displayable notification badge
∘ 4. Use Locator Chaining to go back to the parent elements
· Zhimin’s notes

One Selenium Test Failed

This test (for my fathers’ WhenWise app) is to verify if a group training is available on Saturday, marked with the number in a red circle.

The test passed yesterday. After a code change, the test started to fail with the below comparison error.

Failure/Error: try_for(2) { expect(select_training_class_page.first_available_date_label_regardless_displayed).to include("SAT") }
RuntimeError:
Timeout after 2 seconds with error: expected "FRI\n30/12" to include "SAT"

Diff:
@@ -1,2 +1,3 @@
-SAT
+FRI
+30/12

It seemed to select the “FRI” tab instead of “SAT”. What went wrong here?

Analyse

It could be a bad code change. However, there was actually no visible change on the week selection page.

Visually, the notification badge (red circle) was still on Saturday, and there was nothing on Friday. Visually, exactly how it was before. But something has changed since yesterday, as we got a good run in the BuildWise CT server yesterday.

Zhimin: This shows the importance of daily automated end-to-end (via UI) regression testing, help narrow down regressin issues quickly. By the way, this issue won’t be found by unit testing or integration testing.

This means that we need to update the test script.

The Problem — Multiple Elements

Here is the method in the test script to select the label’s text, first_available_date_label:

def first_available_date_label
  driver.find_element(:xpath, "//div[@class='carousel-item carousel-fixed-item active']//li/div/div[@class='noti-count' and text()='1']/../..").text
end

It retrieves the text for the tab which contains a div with a class noti-count where the notification count is 1.

I used TestWise’s attach-to-browser functionality to check how many divs’ have a class noti-count where the notification count is 1.

elems = driver.find_elements(:xpath, "//div[@class='carousel-item carousel-fixed-item active']//li/div/div[@class='noti-count' and text()='1']")
puts elems.count

The result of this is 2!

Zhimin: Checking the number of elements that matching the lcoator, is a good web testing technique.

I extracted the HTML source and pasted it into a text editor to verify this.

Sure enough, Friday did have a notification badge too, but not displayed. It had a style of display:none.

The Cause: a recent change removed one step of filtering, not-matching-criteria group lessons would still be kept on the page, but their notification counts were hidden.

Knowing why the test was failing, I moved on to fixing the first_available_date_label method.

The Solution — Locator Chaining

Starting where the debugging left off — we now have two notification elements on Friday and Saturday. We just want to retrieve one that is visible.

Previously, I used driver.find_element(:xpath, “//div[@class=’carousel-item carousel-fixed-item active’]//li/div/div[@class=’noti-count’ and text()=’1']/../..”).text to find the tab with the notification element. As you can see, it is quite a long Xpath expression, and adding more constraints to find the correct one might be complex.

I used a different approach:

  1. Finding all elements with a notification badge (regardless of whether they are displayed or not)

  2. Filter out non-displayable ones

  3. Get the first displayed notification badge

  4. Somehow get the tab text based on the notification badge

1. Find all matching elements

elems = driver.find_elements(:xpath, "//div[@class='carousel-item carousel-fixed-item active']//li/div/div[@class='noti-count' and text()='1']")

The returned is a list of Elements.

2. Filter for displayed elements

Then keep the elements that are displayed (without the style of display:none).

To filter by a list in Ruby, we can use the select function. Selenium has an elem.displayed? method, which checks if the element is visible and returns a boolean.

# only keep elements that are visible
display_elems = elems.select{|x| x.displayed? }

At this point, we have the correct tabs in display_elems.

3. Get the first displayable notification badge

the_notification_badge_element = display_elems.first

However, this contains the notification element, it is relative to the tab, but not the tab (i.e. the text here is 1 not FRI 30/12).

4. Use Locator Chaining to go back to the parent elements

Keep reading with a 7-day free trial

Subscribe to The Agile Way to keep reading this post and get 7 days of free access to the full post archives.

Already a paid subscriber? Sign in
© 2025 Zhimin Zhan
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share