Features

Selenium WebDriver Exception handling

  • Share on Facebook
  • Share on Twitter
  • Share on LinkedIn
  • Share on HackerNews

Selenium WebDriver is one of the most popular tools for automating web application testing. Even though Selenium is a very robust test framework, there are common pitfalls that can lead to exceptions (error messages) during test execution.

Exception handling is a crucial skill for any Selenium tester, as it helps to improve test robustness, prevents abrupt failures and provides insight into underlying issues.

In this article we will explore the top 5 exceptions that are commonly encountered in Selenium WebDriver tests and offer solutions or workarounds.

NoSuchElementException

The NoSuchElementException occurs when Selenium WebDriver is unable to locate an element on the webpage. This exception is typically thrown when:

  • The element locator is incorrect or has changed.
  • The element takes time to load and the test script attempts to interact with the element, before it appears on the page or is present in the DOM.
  • The page is dynamic and the elements are being updated in real-time (for example through AJAX or JavaScript and WebSockets).

There are some strategies you can use to prevent this type of exception. Some of the most useful workarounds or preventions include:

  • Double-check the Locator: Make sure the locator (e.g., By.id(), By.xpath(), By.cssSelector()) is accurate and it uniquely identifies the element you want to interact with.
  • Use Explicit Waits:

    Use WebDriver's explicit waits (WebDriverWait) to wait until a specific element condition is met, ensuring the element is present before interacting with it.

    Copy code
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));
  • Dynamic Locator Strategies: If the element locator is dynamic, consider using more flexible locators like XPath or CSS selectors to match patterns, or use attributes that are more stable over time.
  • Page Synchronization: Use synchronization techniques to make sure the webpage is fully loaded before interacting with the elements.

StaleElementReferenceException

The StaleElementReferenceException occurs when the reference to an element is no longer valid. This generally happens when:

  • The DOM has been updated or changed after the element was located.
  • The page has been refreshed, causing previously referenced elements to become "stale."

Here are some strategies you can use to prevent StaleElementReference exceptions.

  • Re-locate the Element:

    When the exception occurs, attempt to re-locate the element to get a fresh reference.

    Copy code
    WebElement element = driver.findElement(By.id("dynamicElement"));
    // Perform actions here
    element = driver.findElement(By.id("dynamicElement")); // Re-locate after a change in the DOM
  • Use Explicit Waits:

    Explicit waits can help to ensure that elements are interacted with only after the DOM has stabilized.

    Copy code
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    WebElement element = wait.until(ExpectedConditions.refreshed(
        ExpectedConditions.visibilityOfElementLocated(By.id("dynamicElement"))));
  • Try-Catch Block: Implement a try-catch block to handle the StaleElementReferenceException and re-attempt the action after a small wait.

TimeoutException

The TimeoutException occurs when a command or wait fails to complete within a specified time. This usually happens when:

  • An explicit wait condition is not met within the allotted time.
  • The page takes longer than expected to load.
  • Network or server issues are slowing down page response times.

Some possible workarounds for timeout exceptions are listed below:

  • Increase Timeout Duration:

    Increase the wait time for WebDriverWait or page load time to accommodate slower loading pages.

    Copy code
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
  • Use Multiple Wait Strategies:

    Combine different types of waits (implicit, explicit, or fluent waits) to handle different scenarios effectively.

    Copy code
    FluentWait<WebDriver> wait = new FluentWait<>(driver)
        .withTimeout(Duration.ofSeconds(30))
        .pollingEvery(Duration.ofSeconds(2))
        .ignoring(NoSuchElementException.class);
    WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("slowElement")));
  • Check Network Conditions: If the issue is related to network instability, consider running tests during low-traffic hours or using local test environments to avoid such delays.

ElementNotInteractableException

The ElementNotInteractableException is thrown when an element is present in the DOM but is not interactable. This can happen when:

  • The element is hidden (e.g., hidden input fields or elements with display: none CSS).
  • The element is covered by another element, such as a loading spinner or popup.
  • The element has not yet loaded completely.

Some possible solutions to prevent not-interactable exceptions include:

  • Scroll Into View:

    If the element is present but not visible, use JavaScript to scroll it into view before interacting with it.

    Copy code
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("arguments[0].scrollIntoView(true);", element);
  • Wait for Visibility:

    Use an explicit wait to ensure the element is visible before interacting with it.

    Copy code
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("buttonId")));
  • Handle Overlapping Elements:

    Ensure there are no other elements (e.g., popups) overlapping the target element. Consider using JavaScript to click the element if it remains covered.

    Copy code
    js.executeScript("arguments[0].click();", element);

WebDriverException

The WebDriverException is a generic exception that can occur due to many reasons, such as:

  • Issues with the WebDriver executable (e.g., ChromeDriver, GeckoDriver) not starting or stopping unexpectedly.
  • Browser crashes or WebDriver losing the connection to the browser instance.
  • Incompatibility between the WebDriver and the browser version.

The number one workaround for these type of exceptions is to use TestingBot! We make sure machines are properly updated, have adequate CPU + RAM and that all versions are compatible.

  • Match WebDriver and Browser Versions:

    Ensure the WebDriver version matches the browser version. For example, ChromeDriver should be compatible with the installed version of Chrome.

  • Check System Resources:

    If browser crashes are frequent, make sure that the system has adequate resources (CPU, RAM and IO) to run both the tests and the browser.

    Copy code
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("buttonId")));
  • Handle Overlapping Elements:

    Ensure there are no other elements (e.g., popups) overlapping the target element. Consider using JavaScript to click the element if it remains covered.

    Copy code
    js.executeScript("arguments[0].click();", element);

General Exception Handling Strategies in Selenium WebDriver

While specific solutions for the top exceptions are essential, having a general strategy for handling unexpected exceptions in Selenium WebDriver can significantly improve your test reliability. Below we will go over a few effective strategies that you can utilize.

1. Graceful Error Handling

Implement try-catch blocks in your test code to handle exceptions gracefully without causing abrupt test failures.

Copy code
try {
    WebElement element = driver.findElement(By.id("someElement"));
    element.click();
} catch (NoSuchElementException e) {
    System.out.println("Element not found, skipping test.");
}

2. Retry Logic

For flaky tests, implement retry logic to attempt actions more than once in case of failure. This helps deal with intermittent issues such as network latency or timing issues.

Copy code
public void clickWithRetry(By locator, int attempts) {
    int retries = 0;
    while (retries < attempts) {
        try {
            driver.findElement(locator).click();
            return;
        } catch (Exception e) {
            retries++;
            if (retries == attempts) {
                throw e;
            }
        }
    }
}

3. Page Object Model (POM)

Implementing a Page Object Model can reduce the impact of changes in the DOM and make exception handling more centralized and efficient. By encapsulating element locators and interactions, it's easier to handle changes and exceptions in one place.

Copy code
public class LoginPage {
    private WebDriver driver;
    private By usernameField = By.id("username");
    private By passwordField = By.id("password");
    private By loginButton = By.id("loginBtn");

    public LoginPage(WebDriver driver) {
        this.driver = driver;
    }

    public void login(String username, String password) {
        driver.findElement(usernameField).sendKeys(username);
        driver.findElement(passwordField).sendKeys(password);
        driver.findElement(loginButton).click();
    }
}

4. Logging and Reporting

Add logging to track what happens during test execution, especially in the event of an exception. Libraries like Log4j can be integrated with Selenium to provide detailed logs, which are extremely helpful for diagnosing issues.

Copy code
import org.apache.log4j.Logger;

public class TestLogger {
    private static Logger log = Logger.getLogger(TestLogger.class);

    public static void main(String[] args) {
        log.info("Test execution started");
        try {
            // Test code here
        } catch (Exception e) {
            log.error("An error occurred: ", e);
        }
        log.info("Test execution ended");
    }
}

5. Use TestingBot

Selenium Grids such as TestingBot's Grid, can be highly beneficial in preventing some of the common exceptions encountered in Selenium WebDriver tests. By distributing test execution across multiple environments and configurations, TestingBot Grid helps with:

  • Reduced Test Flakiness:

    Running tests in parallel on multiple browsers and operating systems helps in identifying environment-specific issues, thus reducing flakiness.

  • Improved Resource Utilization:

    The TestingBot Grid allows scaling up test execution by running tests simultaneously, reducing the load on individual systems and improving reliability.

  • Testing Different Configurations:

    TestingBot's Selenium Grid offers access to a wide range of browser and operating system configurations, ensuring that issues like WebDriverException due to incompatibility can be identified and addressed early.

  • Share on Facebook
  • Share on Twitter
  • Share on LinkedIn
  • Share on HackerNews
TestingBot Logo

Sign up for a Free Trial

Start testing your apps with TestingBot.

No credit card required.

Other Articles

How to write a Test Strategy Document?

Learn how to create a test strategy document. This is a document that outlines what needs to be tested at which stage of the build process.

Read more
An alternative to mabl's low-code automation framework: TestingBot

Convert Mabl tests to be used with TestingBot's cloud-based browser grid. Improve performance, test coverage and reliability.

Read more
Inject webcam and microphone feeds during Selenium testing.

Find out how to run automated browser tests with a fake microphone and webcam.

Read more
Javascript Test Frameworks: Top 15

An overview of the top 15 Javascript Testing Frameworks

Read more
Automated Browser Extension Testing

Learn how to perform automated testing against browser extensions.

Read more
The best Python Web Testing frameworks

A top 5 of the best Python Test Frameworks available for automated website testing.

Read more