Selenium Page locator strategies and NoSuchElementException

Veeresh Bikkaneti
LetsAutomateWithSelenium
4 min readMay 30, 2020

This article is to help beginners understand various available options and quick hacks to identify page elements.

Background:

Many automation testers detail with a pretty common issue: “NoSuchElementException”.

  1. This could be due to the poor choices and decisions made early in the design phase; that will haunt test projects or apps throughout the life of the product.
  2. Synchronization could be another common reason;
    little or no wait time
    or
    the type of Wait implemented. And,
  3. Adding the frequent code changes; this result in revisiting all the page objects.

Available Selenium Locator Strategies:

Selenium 3.0 Page Locator Strategy:

CSS can be used in combination with attributes to identify a unique element

Order of precedence for searching/ identifying a Web element:

ID, Class Name, CSS Selectors, Xpath. While searching for an element using Xpath will take longer time compared to CSS Selector.

Selenium 4.0 Locator Strategies:

Relative Locators which are previously called as Friendly Locators

Selenium 4 Page locator Strategies
Webdriver interface and key methods

Consider we have a fully functional web browser and the application under test (web url ) is loaded successfully.

For automating this context, Selenium Web driver interface is instantiated with its implementations. Web Page is loaded and elements are displayed.

Before instantiating a Webdriver implementation; We should show the path where the binary or the actual .exe file is located as below:

Step#1

System.setProperty("webdriver.chrome.driver", "/path/to/driver.exe");//Setup Webdriver binary

OR

Step#1

<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${LATEST.version}</version>
<scope>test</scope>
</dependency>
Setup Webdriver binary using Bonigarcia

Step#2

Swapping Webdriver Interface with a fully featured browser

Handling Synchronization issue:

Strategy#1:Using Implicit Waits


//instantiating the webdriver
WebDriver webDriverInstance = new ChromeDriver( );

//navigate to the url
webDriverInstance.navigate( ).to("https://www.google.com/");

//navigate to the url
webDriverInstance.get("https://www.google.com/");

/*
Sets the amount of time to wait for a page load to complete before throwing an error.
*/
webDriverInstance
.manage( )
.timeouts( )
.pageLoadTimeout(Long.valueOf(20), TimeUnit.SECONDS);

/*Specifies the amount of time the driver should wait when searching for an element if it is not immediately present.
Max amount of time that a Webdriver Instance will wait before throwing NoSuchElementException
*/
webDriverInstance
.manage( )
.timeouts( )
.implicitlyWait(Long.valueOf(20), TimeUnit.SECONDS);

Strategy#2:Explicit waits/ WebdriverWait

Strategy#3: FluentWaits

Implementing Step#1 and 2 will instantiate the webdriver and load the AUT url or the web page and wait for a maximum of 20 seconds before searching for any elements or throwing a “NoSuchElementException”.

Explicit Wait:

The Selenium WebDriver provides the WebDriverWait and ExpectedConditions classes to implement an explicit wait.

The ExpectedConditions class provides a set of predefined conditions to wait for before proceeding further in the code

/*
Wait will ignore instances of NotFoundException that are encountered (thrown) by default in
the 'until' condition, and immediately propagate all others. You can add more to the ignore
list by calling ignoring(exceptions to add).
*/
assertTrue
(new WebDriverWait(webDriverInstance, Long.valueOf(20))
.until(ExpectedConditions.titleIs( "Google")).booleanValue(),"*****Url not loaded*****");
using By.Name()

We shall now explore multiple strategies to uniquely identify the Search box:

By searchByName = By.name("q");
By searchByCSSselector = By.cssSelector(".a4bIc > input[role='combobox']");
By searchByAbsoluteXpath = By.xpath("/html/body/div/div[4]/form/div[2]/div[1]/div[1]/div/div[2]/input");
By searchByRelativeXpath = By.xpath("//input[@title='Search']");

Employing any of the above strategies would still find the same element from the DOM; In the above scenario By.name will return the element first and cssSelector will be second and xpath will be the last as the control has to traverse from each node specified to get to the actual element.

sample css breakdown
xpath

Advantage of using Xpath:

Traverse in both directions backwards to parent nodes and forward to child nodes and subsequent nodes.

Disadvantage:

Traverse only oneway forward

http://the-internet.herokuapp.com/tables

Accessing the 2nd row and 5th column:

By.cssSelector("table#table1 tr:nth-of-type(2) > td:nth-of-type(5)")
By.xpath("(//tr[2]) [1]//td[5]")
xpath to traverse backwards and forward to read table

https://github.com/veerNeti/beginnersguidefortesting/blob/master/src/test/java/com/guide/beginners/testng/theinternet/individualtestclass/HandlingTables.java

--

--