How To…Selenium: Manage Selenium WebDriver Exceptions

Each month on the first Tuesday of the month, we will post a new blog post to take you through a step-by-step guide on how to address a particular aspect of a tool, platform or device that you might need to address in your testing.

The series continues with Alec Siminiuc on different aspects of Selenium that you might need to cover as part of your testing.

You can read Alex’s previous posts here:

How To…Select Elements In Selenium WebDriver Scripts

How To…Use Explicit Waits In Selenium WebDriver

We will be addressing different topics, testing tools, platforms over the series. If you have a request for one topic to be addressed then please comment below. Alternatively you can add the request to our How To..Series thread in the forum.

 

———————————————————————————————————————————————–

When an error occurs in a test automation script, an exception is being thrown. Exceptions in Selenium webdriver happen for many reasons.


Exceptions are used to signal that an error or exceptional situation has occurred.


When an exception is generated, the test method execution is stopped and the remaining code is ignored. 


A test automation method may throw an exception for many reasons, for instance if a web element cannot be found. 


For example, the following test method throws an exception on its 3rd line: 

@Test
public void findSearchTextBox() 

{
 By incorrectSearchTextBoxLocator = By.xpath("//input[@id='globalQuery1']");  driver.get("http://www.vpl.ca"); 
 WebElement searchTextBox = driver.findElement(incorrectSearchTextBoxLocator);

The third line tries finding the searchTextBox element. 


Because the element’s XPATH locator is incorrect, the code throws an exception with the following details: 




org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"//input[@id='globalQuery1']"}
Command duration or timeout: 31 milliseconds
........................................................................
*** Element info: {Using=xpath, value=//input[@id='globalQuery1']}
Session ID: 38e9d95c-bee0-46e7-986e-1cbf9cbc3a79
Driver info: org.openqa.selenium.firefox.FirefoxDriver
Capabilities [{platform=WINDOWS, acceptSslCerts=true, javascriptEnabled=true, cssSelectorsEnabled=true, databaseEnabled=true, browserName=firefox, handlesAlerts=true,
........................................................................
........................................................................
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:355)
at ThrowExceptions.findSearchTextBox(ThrowExceptions.java:92)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 



The exception uses the NoSuchElementException exception class. 


CATCHING EXCEPTIONS 

The previous test method threw a NoSuchElementException exception when the searchTextBox element could not be found. 


The exception can be caught and handled with a try-catch block. 

@Test
public void findSearchTextBox() 

{
 By incorrectSearchTextBoxLocator = By.xpath("//input[@id='globalQuery1']");
 driver.get("http://www.vpl.ca"); 
 try
 {
   WebElement searchField = driver.findElement(incorrectSearchTextBoxLocator);
 }
 catch(NoSuchElementException exception) 
 {
  System.out.println("search text box not found"); 
 } 


The NoSuchElementException parameter exception inside the catch-clause points to the exception thrown from the findSearchTextBox() method.


If no exception is thrown by the code inside the try-block, the catch-block is simply ignored.


Because of the try/catch block, the test method does not fail any longer. 


Instead, it displays an error message in the Console and then it passes. 


The fact that the test method passes is obviously not correct since it just had a error in it.


FINALLY CLAUSE  

Instead of displaying a message in the console, we want the test method to fail and display a user friendly error message in the JUNIT view. 


We can do this in multiple ways.


1. by failing the test method in the catch() clause 


This is done using the fail() JUNIT method which is equivalent to an assertion that fails.


@Test
public void findSearchTextBox() 

{
 By incorrectSearchTextBoxLocator = By.xpath("//input[@id='globalQuery1']");
 driver.get("http://www.vpl.ca"); 
 try
 {
  WebElement searchField = driver.findElement(incorrectSearchTextBoxLocator);
 }
 catch(NoSuchElementException ex) 
 {
   fail("search text box not found"); 
 } 


The test script fails properly with the following error:


java.lang.AssertionError: search text box not found
at org.junit.Assert.fail(Assert.java:88)
at ThrowExceptions.findSearchTextBox(ThrowExceptions.java:160)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)

………………………………………………….



2. by adding a finally clause to the try/catch block 


Lets change the test method by adding to the catch clause code that logs the exception details. 


@Test
public void findSearchTextBox() throws IOException 

{
 By incorrectSearchTextBoxLocator = By.xpath("//input[@id='globalQuery1']");

 driver.get("http://www.vpl.ca"); 
 try
 {
   WebElement searchField = driver.findElement(incorrectSearchTextBoxLocator);
 }
 catch(NoSuchElementException exception) 
 { 
   openLog(); 
   addToLog(exception.getMessage()); 
   closeLog();  
   fail("search text box not found"); 
 } 



Lets assume that the addToLog() can generate an IOException. 


When the IOException is generated, the last 2 lines of the catch clause are ignored so the log is not closed. 


And the test method fails because of an exception that is not caught (IOException).


We can fix this by adding a finally clause to the try/catch block. 


The code inside the finally clause will always be executed, even if an exception is thrown from within the try or catch block. 


@Test
public void findSearchTextBox() throws IOException 

{
  By incorrectSearchTextBoxLocator = By.xpath("//input[@id='globalQuery1']");
  driver.get("http://www.vpl.ca"); 
  try
  {
    WebElement searchField = driver.findElement(incorrectSearchTextBoxLocator);
  }
  catch(NoSuchElementException exception) 
  { 
    openLog(); 
    addToLog(exception.getMessage()); 
  } 
  finally 
  { 
    closeLog(); 
    fail("search text box not found"); 
  } 



In this case, the test script fails properly after the log is closed: 


java.lang.AssertionError: search text box not found
at org.junit.Assert.fail(Assert.java:88)
at ThrowExceptions.findSearchTextBox(ThrowExceptions.java:160)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)

………………………………………………….
Info

THROWING CUSTOM EXCEPTIONS

So far, we failed the test script using the fail() JUNIT method. 


This works and provides the following details in the JUNIT view: 

  • the user friendly error message
  • the stack trace 

But we could end the test method in a better way. 


First, we remove fail() from the finally clause. 


Then, since the addToLog() method throws an IOException exception, we catch this exception with a second try/catch block. 


And in the second catch clause, we re-throw the exception using a custom exception class:

@Test
public void findSearchTextBox() throws IOException, ElementNotFoundException 

{
 By incorrectSearchTextBoxLocator = By.xpath("//input[@id='globalQuery1']");

 driver.get("http://www.vpl.ca"); 
 try
 {
   WebElement searchField = driver.findElement(incorrectSearchTextBoxLocator);
 }
 catch(NoSuchElementException exception) 
 { 
   openLog(); 
   try 
   { 
     addToLog(exception.getMessage()); 
   } 
   catch (IOException ex) 
   { 
     throw new ElementNotFoundException("search text box not found", exception); 
   } 
 } 
 finally 
 { 
   closeLog();
 } 


The test script still fails but we have more information displayed in the JUNIT view:

  • the user friendly error message 
  • the name of a custom exception class 
  • the exception details 

ElementNotFoundException: search text box not found
at ThrowExceptions.findSearchTextBox5(ThrowExceptions.java:181)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
..................................................................
Caused by: org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"//input[@id='globalQuery1']"}
Command duration or timeout: 37 milliseconds
...................................................................
Session ID: 15f68d69-4623-4de3-865f-df78d1ae3136
Driver info: org.openqa.selenium.firefox.FirefoxDriver
Capabilities [{platform=WINDOWS, acceptSslCerts=true, javascriptEnabled=true, cssSelectorsEnabled=true, databaseEnabled=true, browserName=firefox, handlesAlerts=true, nativeEvents=false, webStorageEnabled=true, rotatable=false, locationContextEnabled=true, applicationCacheEnabled=true, takesScreenshot=true, version=37.0}]
................................................................
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:355)
at ThrowExceptions.findSearchTextBox5(ThrowExceptions.java:170)
... 25 more
Caused by: org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"//input[@id='globalQuery1']"} 


SELENIUM COMMON EXCEPTIONS


See below the list of common exceptions that can be generated by the Selenium WebDriver library.


selenium.common.exceptions.ElementNotSelectableException

Thrown when trying to select an unselectable element.

exception


selenium.common.exceptions.ElementNotVisibleException

Thrown when an element is present on the DOM, but it is not visible, and so is not able to be interacted with. 
Most commonly encountered when trying to click or read text of an element that is hidden from view. 


selenium.common.exceptions.ErrorInResponseException(response, msg)


Thrown when an error has occurred on the server side. 
This may happen when communicating with the firefox extension or the remote driver server. 


selenium.common.exceptions.InvalidCookieDomainException


Thrown when attempting to add a cookie under a different domain than the current URL.


selenium.common.exceptions.InvalidElementStateException
selenium.common.exceptions.InvalidSelectorException


Thrown when the selector which is used to find an element does not return a WebElement. 


Currently this only happens when the selector is an xpath expression and it is either syntactically invalid (i.e. it is not a xpath expression) or the expression does not select WebElements (e.g. “count(//input)”). 


selenium.common.exceptions.InvalidSwitchToTargetException


Thrown when frame or window target to be switched doesn’t exist. 


selenium.common.exceptions.NoAlertPresentException


Thrown when switching to no presented alert. 
This can be caused by calling an operation on the Alert() class when an alert is not yet on the screen. 


selenium.common.exceptions.NoSuchAttributeException


Thrown when the attribute of element could not be found. 
You may want to check if the attribute exists in the particular browser you are testing against. 
Some browsers may have different property names for the same property. (IE8’s .innerText vs. Firefox .textContent) 


selenium.common.exceptions.NoSuchElementException


Thrown when element could not be found. 


If you encounter this exception, you may want to check the following:
Check your selector used in your find_by…
Element may not yet be on the screen at the time of the find operation,
(webpage is still loading) see selenium.webdriver.support.wait.WebDriverWait() for how to write a wait wrapper to wait for an element to appear. 



selenium.common.exceptions.NoSuchFrameException


Thrown when frame target to be switched doesn’t exist. 


selenium.common.exceptions.NoSuchWindowException


Thrown when window target to be switched doesn’t exist. 
To find the current set of active window handles, you can get a list of the active window handles in the following way:
print driver.window_handles 



selenium.common.exceptions.StaleElementReferenceException


Thrown when a reference to an element is now “stale”. 


Stale means the element no longer appears on the DOM of the page. 


Possible causes of StaleElementReferenceException include, but not limited to: 

  1. You are no longer on the same page, or the page may have refreshed since the element
    was located. 
  2. The element may have been removed and re-added to the screen, since it was located. Such as an element being relocated. 
  3. Element may have been inside an iframe or another context which was refreshed. 

Info

selenium.common.exceptions.TimeoutException


Thrown when a command does not complete in enough time. 


selenium.common.exceptions.UnableToSetCookieException


Thrown when a driver fails to set a cookie. 


selenium.common.exceptions.UnexpectedAlertPresentException


Thrown when an unexpected alert is appeared. 
Usually raised when when an expected modal is blocking webdriver form executing any more commands. 


selenium.common.exceptions.UnexpectedTagNameException


Thrown when a support class did not get an expected web element. 


selenium.common.exceptions.WebDriverException


Base webdriver exception.


See more details on this link.

Thank you for checking out this post on Exceptions in Selenium WebDriver.

See more articles in the How To Selenium Series

 

 

About the Author

Alex

Software Tester from Vancouver, Canada. Blogs on test automation topics for manual testers on http://test-able.blogspot.ca When not testing or creating test automation scripts for my clients, I teach manual testers programming with Java and test automation with Selenium WebDriver.
Find out more about @alexsiminiuc