July 30, 2020 Jonny Steiner

How to handle exceptions in Selenium WebDriver

Share this knowledge!

Introduction

Using Selenium WebDriver to develop complex software comes with risks. One of the main ones is that an issue in one module can prevent the execution of the whole program.

This brings us to exceptions. Basically, an exception is an event, which occurs during the execution of a program that disrupts the normal flow of the program instructions. Often, it’s unacceptable to allow a whole application to crash when something went wrong in a part of it. That’s why we need exception handling. The whole idea behind exception handling is to determine a place in a code, where something might get wrong and make sure that a program can take an alternative route in case of an error. It’s vital for software development to properly handle exceptions, and even more so for a process of automated testing.

In this article, we will look at how to handle exceptions in Java in general, and in Selenium WebDriver in particular.

Exception handling in Java

Why is it important to handle exceptions? Well, there are two main reasons:

  1. You can use throw keyword to print a custom message for an exception, making the reporting easier.
  2. In some cases, you may want to make an alternative flow when you catch an exception. You can write any specific code, and execute it when an exception occurs inside the catch block.

In Java, there are 5 keywords to handle an exception:

  • try – Used to specify a block in a code, where we might expect an exception to occur. Try block follows either a catch block or a final block.
  • catch – In this block, we put executable code in case of an exception in a try block. Catch blocks must follow try blocks and lead to the final block.
  • throw – Used to explicitly throw an exception. It is mainly used to throw custom exceptions.
  • throws – Used to specify particular exceptions that occur in a class.
  • finally – This block specifies an important piece of executable code, no matter if you catch an exception or not. Useful, when you need to perform mandatory steps such as clean-ups and closing connections.

Example:

public void myClass() {
   try {
       //A code that may cause exception goes here
   } catch(Exception e) {
       //What to do in a case of exception
   } finally {
       //Add here a code, that has to be executed anyway
   }
}

 

When encountering an exception in a try block, then this exception passes as a parameter to a catch block. It is possible to have multiple catch blocks if you want to handle different types of exceptions in different ways.

Common Selenium WebDriver exceptions

All the exceptions in Selenium WebDriver are subclasses of WebDriverException class, which, in order, a subclass of Java RuntimeException.

I’ve shown the hierarchy of WebDriver exceptions below:

Selenium WebDriver

  • ConnectionClosedException – An exception throws when losing the connection to the driver.
  • InvalidArgumentException – This exception throws if any argument, provided to the web-driver doesn’t belong to an expected type.
  • InvalidCoordinatesException – Indicates that the coordinates provided to an interaction operation are invalid. This, most likely, means that a move operation was provided with invalid coordinates, or an action that depends on a pointer mouse position (like click) was not preceded by a move operation.
  • ElementNotVisibleException – Throws to indicate that although an element is present on the DOM, it is not visible, and so it’s impossible to interact with it.
  • ElementClickInterceptedException – Indicates that a click on a target element could not be properly executed because it obscured the target element in some way.
  • NoSuchSessionException – Throws by any command called after WebDriver.quit().
  • NoSuchElementException – Throws by WebDriver.findElement(By by) and WebElement.findElement(By by) when finding no element.
  • NoSuchAttributeException – Shows that a requested attribute is not available in DOM.
  • SessionNotCreatedException – States that it could not create a session.
  • StaleElementReferenceException – Indicates that a reference to an element is now “stale” — the element no longer appears on the DOM of the page.
  • TimeoutException – Throws when a command does not complete in enough time.

Handling exceptions in Selenium WebDriver

Let’s see common examples of handling exceptions in Selenium WebDriver with Java and SeeTest.

First of all, let’s make our test class:

import java.net.MalformedURLException;
import java.net.URL;

import org.junit.After;
import org.junit.Test;
import static org.junit.Assert.assertEquals;


import org.openqa.selenium.SessionNotCreatedException;
import org.openqa.selenium.remote.BrowserType;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;


public class ExceptionsTest {

   private RemoteWebDriver driver;
   private static final String ACCESS_KEY = System.getenv("SEETEST_IO_ACCESS_KEY");
private WebDriverWait wait;

public ExceptionsTest () {
   DesiredCapabilities dc = new DesiredCapabilities();
   dc.setCapability("generateReport", true);
   String title = "Selenium Test";
   dc.setCapability("accessKey", ACCESS_KEY);
   String Selenium_Hub = "https://cloud.seetest.io/wd/hub/";
   dc.setCapability(CapabilityType.BROWSER_NAME, BrowserType.CHROME);
   dc.setCapability("testName", title);

   try {
       driver = new RemoteWebDriver(new URL(Selenium_Hub), dc);
       wait = new WebDriverWait(driver, 10);

       } catch (MalformedURLException e) {
           System.out.println("Malformed URL: " + Selenium_Hub);
       } catch (SessionNotCreatedException e) {
           System.out.println("Wrong SeeTest access key" + ACCESS_KEY);
       }
   }

@After
public void tearDown() {
   if (driver != null) {
       driver.quit();
   }
}


}


 

Here we declared our test class and made a constructor to set desired capabilities, indicating that we want to connect web-driver to the Chrome browser on the SeeTest platform. As you can see, here we made a try…catch block, to handle cases when a URL to SeeTest hub is malformed or SeeTest access token is incorrect.

Now, let’s write a simple test:


@Test
public void testSelenium() {
   driver.get("https://seetest.io");
   try {
       assertEquals(driver.findElement(By.xpath("/html/body/section/div/div[1]/div[1]/div")).getText(), "START TESTING NOW");
   } catch (NoSuchElementException e) {
       throw new RuntimeException("Can't find \"START TESTING NOW\" button");

   }
}

Here we visit https://seetest.io page and check if the “START TESTING NOW” button exists. If Selenium WebDriver is not capable of locating such an element, then our test will fail and we get a description of what exactly went wrong.

Let’s see another example:

@Test
public void testSelenium_wait() {
   driver.get("https://seetest.io");
   try {
       driver.findElement(By.xpath("/html/body/section/div/div[1]/div[1]/div/a")).click();
   } catch (TimeoutException e) {
       wait.until( ExpectedConditions.elementToBeClickable(By.xpath("//*[@id='register']")));
       driver.findElement(By.xpath("/html/body/section/div/div[1]/div[1]/div/a")).click();
   } catch (NoSuchElementException e) {
       throw new RuntimeException("Can't find \"START TESTING NOW\" button", e);
   }
}

Here we use two catch blocks to perform different actions for different exceptions. The first catch block waits for TimeoutException to occur, and when such exception is being caught, it waits for a specified element to become clickable. The second catch block intercepts NoSuchElementException and outputs a message that no elements found.

Let’s imagine a situation, when we need to check that particular element is not appearing on a page. So, in this test, we try to find a specific element and if a web driver isn’t able to find such an element, we catch NoSuchElementException and consider our test passed by assertEquals(true, true).

@Test
public void testSelenium2() {
   driver.get("https://seetest.io");
   try {
       driver.findElement(By.xpath("/html/body/section/div/div[1]/div[1]/div/a")).click();
   } catch (NoSuchElementException e) {
       assertEquals(true, true);
       return;
   }
   assertEquals(true, false);
}

Conclusion

Proper exception handling is very important for automated testing. Thanks to smart placement of try…catch blocks you can always have explanatory reports on the behavior of your tests. For example, when you see a TimeoutException in your report it may indicate that there are some problems with performance, thus you should increase wait times for a driver or operation. Plus, it helps you to make your tests more flexible and responsive. For more have a look at another blog post we did on a connected topic.

Guy ArieliCTO

Share this knowledge!