Most web tests involve interacting with elements on a web page. This would not possible without first locating and
retrieving these elements on the page. When the process of locating the elements of interest in the web page fails,
Selenium throws a NoSuchElementException
. This represents one of the most common Selenium exceptions, which is why it
is so important to know about it and how to handle it correctly.
In this article, you will learn what a NoSuchElementException
is, what the most common causes behind this exception
are, and everything you need to know to handle it in your Selenium WebDriver
regression tests.
What is a NoSuchElementException in Selenium?
NoSuchElementException
is one of the most common exceptions in Selenium WebDriver, and it is thrown when an HTML element cannot be found. A
NoSuchElementException
occurs when the
Selenium locator strategy defined is unable to
find the desired HTML element in the web page.
NoSuchElementException
derives from
NotFoundException
and is
thrown by
WebDriver.findElement
and
WebElement.findElement
as below:
|
|
When Selenium is not able to locate the HTML element with id “foo-button”, the following NoSuchElementException
is
thrown:
|
|
There are a few reasons why a NoSuchElementException
can occur. Let’s now delve into them.
When Does NoSuchElementException Occur in a Selenium Test?
There are two main reasons for a NoSuchElementException
:
- The Selenium locator strategy you adopted does not identify any HTML element in the
DOM. There’s a few ways this can occur:
- The HTML element is not yet present in the web page, just when the desired element is rendered asynchronously as a result of an AJAX call.
- The HTML element appears in the web page only after certain operations are performed.
- The HTML element is not present in the web page, no matter what.
- The HTML element you are trying to locate is inside an
<iframe>
element.
How To Handle NoSuchElementException in Selenium?
There are two ways to deal with NoSuchElementException
.
Using WebDriverWait
WebDriverWait
allows you to wait for an HTML element to satisfy a specific condition defined through the
ExpectedConditions
class. For example, you can use it to wait some seconds until the HTML element you are looking for is present in the DOM
as below:
|
|
This avoids a NoSuchElementException
due to incomplete page loading. If the “foo-button” HTML element is not displayed
in 10 seconds after calling the until()
method, then a TimeoutException
will be thrown. This exception will be
introduced later.
Consider that the approach presented above may not be sufficient when dealing with AJAX calls. This is especially true when it comes to web apps developed in React, Vue, or Angular that make heavy use of API calls to retrieve data. In this scenario, you may need a more sophisticated approach involving a polling process. You can implement it as follows:
|
|
The third parameter passed to WebDriverWait
defines the duration of the sleep time between polls.
Notice that WebDriverWait
ignores NotFoundException
s thrown by the
until()
method by default, but immediately propagates all other exceptions. Therefore, also NoSuchElementException
cannot be
thrown by until()
when calling it on a WebDriverWait
instance.
Using more reliable selectors
The Selenium By
class allows you to
define the locator strategy that Selenium will apply to find HTML elements within a web document. When Selenium fails to
find the HTML element identified with the By
condition, a NoSuchElementException
is thrown.
By
offers several ways to locate an HTML element, but some are more reliable than others. For example, retrieving an
HTML element based on its class
attribute
may not be a good strategy. This is because CSS classes are attributes that can easily change over time.
|
|
If the layout of the web page changes or the “foo-align-right” class name is renamed, this line of code will throw a
NoSuchElementException
.
If you want your Selenium tests to be robust to changes in the target web pages, you need to use more reliable
selectors. When it comes to defining selectors, you should prefer IDs to classes. The
id
attribute of an HTML element identifies
it uniquely and is unlikely to change over time.
|
|
In this case, the selector used to retrieve the HTML element is more reliable.
In general, you should always try to use selectors and locator strategies that are based on the distinctive priorities
of an HTML element. Styling and placement might change many times over time, and relying on them forces you to update
your tests to avoid NoSuchElementException
s.
Other Common Selenium Exceptions That Can Occur
Let’s take a look at the three most common Selenium exceptions remaining.
InvalidSelectorException
InvalidSelectorException
is
thrown by By
when the selector passed as a parameter is a CSS or
XPath expression that is syntactically invalid. You can avoid it
by replacing the selector string used inBy
condition with a valid expression.
Example:
|
|
This is the InvalidSelectorException
error that snippet would cause:
|
|
For more information, check out our article on fixing InvalidSelectorExceptions in Selenium.
ElementNotInteractableException
ElementNotInteractableException
is thrown when an HTML element is present in the DOM but is in a state that cannot be interacted with. Note that this
includes an HTML element that is hidden, or whose center point can not be scrolled into the
browser viewport.
For example, ElementNotInteractableException
is thrown when calling the
click()
method on a
Selenium WebElement
you
momentarily cannot interact with. In this case, you can avoid the exception by employing the
ExpectedCondition.elementToBeClickable
method combined with WebDriverWait
as below:
|
|
If the fooButton
element is in a non-interactable state, the last line would cause the following error:
|
|
TimeoutException
TimeoutException
is
thrown when a command does not complete in enough time. For example, when this exception occurs when an until()
method
on a WebDriverWait
instance does not satisfy the expected conditions in the given time.
Example:
|
|
Notice the typo introduced in the first line in the By
condition. This would cause until()
to fail and the following
TimeoutException
error as a result:
|
|
No More Exceptions With Reflect
When something goes wrong, Selenium raises exceptions. So, you need to know what exceptions your test can raise and how to handle them accordingly. This is a cumbersome process that only experienced developers can deal with. Thankfully, there is a solution to this problem! The solution is called Reflect, a no-code tool that allows you to test your web applications with no exceptions involved.
Let’s understand how powerful Reflect is with an example.
Suppose you want to test adding a product to your e-commerce site’s shopping cart. Specifically, when you click the “Add to basket” button, the site should perform an asynchronous AJAX request to add the product to the cart and show the “View Cart” button. With Selenium, you would have to write some logic to wait for that HTML element to appear. With Reflect, you can simply perform the actions you want to test directly in the browser and define a visual check to wait for the desired element to appear on the page.
As you can see, Reflect records these actions for you and builds a test around them. With just a few clicks, you can define a test involving async logic! This makes testing a lot faster and easier. Stop struggling with exception handling in your tests, try Reflect for free!
Conclusion
In this article, you learned that Selenium WebDriver is a powerful tool to perform automated tests on web applications,
what NoSuchElementException
is and when it occurs, and how to handle it in Java. Considering how frequent the
NoSuchElementException
is, understanding how it happens and being able to use handle it properly is critical to
building robust Selenium WebDriver tests. Here you learned everything you need to know to interact with it and other
common Selenium exceptions. Also, you understood that dealing with exceptions when it comes to testing is cumbersome and
you can avoid all this with a complete no-code testing tool such as Reflect.