Automation Exceptions and Solutions

     We know that an exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program’s instructions. When an error occurs within a method, the method creates an object and hands it off to the runtime system. This block of code is called an exception handler.

     In real world scenario, while working with automation using Selenium WebDriver, automation engineer would definitely come across various exceptions which disrupts the test case execution. The automation script that you work with, sometimes work properly and sometimes it simply doesn’t work. For any script that you develop, make sure that you deliver the best quality code with proper exceptions handling techniques implemented.

     In this article, I would like to share the common exceptions while selenium automation execution and also the solutions to handle those exceptions. Following are the different types of exceptions in selenium,

WebDriverException

     WebDriverException arises when the your code tries to perform any action on the non-existing browser. For example, trying to use driver after closing the driver session.

WebDriver driver = new ChromeDriver();
driver.get(“https://journeyofquality.com/ “);
driver.close();
driver.findElement(By.id(“bu345”)).click();

Solution: You can handle this WebDriverException by using driver.close() after the completion of all tests at @AfterSuite annotation if you are using TestNG instead of using them after each test case that is after all the test execution has completed.

SessionNotFoundException

     SessionNotFoundException will occur when driver is trying to perform operations on the web application after the browser is quitted by driver.quit().

@Test
public void openJourneyOfQuality() {
driver.get(“https://journeyofquality.com/ “);
Assert.assertEquals(“Journey”, driver.getTitle());
driver.quit();
Assert.assertEquals(“https://journeyofquality.com/ “, driver.getCurrentUrl());
}

Solution: This exception can be handled by using driver.quit() after the completion of all tests instead of using them after each test case. This can lead to issues when driver instance becoming null and following test cases try to use it without initializing. We can kill the driver instance after all the test execution has completed and hence we can add them up at @AfterSuite of TestNG annotation.

StaleElementReferenceException

     User would come across StaleElemenReferenceException mainly when Selenium navigates to a different page, come backs to the same old page and performs operations on the old page which is no longer available. Technically, it occurs when the element defined in the script is not found in the cache memory and script is trying to locate it that particular element. When we inspect and locate an element on a page using Selenium, it is stored in a cache memory which gets deleted when the driver navigates to another page during execution. When user navigates back to old page and then while trying to access the cache removed element on the old page, we will get StaleElementReferenceException during the automation script execution.

Solutions:

  • Refresh the webpage and perform action on that web element.
  • Include the web element on try-catch block within for loop to get the element and perform the action. Once it perform the action, it will break from the loop.

for (int value = 0; value <= 2; value++) {
try {
driver.findElement(By.xpath(“webElement”)).click();
break;
} catch (Exception e) {
System.out.println(e.getMessage());
}
}

  • Wait for the element till available by using ExpectedConditions,

wait.until(ExpectedConditions.presenceOfElementLocated(By.id(“webElement”)));

NoSuchElementException

     NoSuchElementException occurs, when the element locators we provided in the Selenium script is unable to find that web element on the web page. Probably this will happen in two ways,

  • When we have provided an incorrect locator and trying to find the web element.
  • We have provided correct locator, but the web element related to the locator is not available on the web page. That means the action performed before loading that element on the web page.

@Test
public void testJourney() {
driver.get(“https://journeyofquality.com/ “);
try {
driver.findElement(By.id(“invalidelement”)).click();
} catch (NoSuchElementException e) {
System.out.println(“No Such Element exceptional case”);
}
}

     In the above code, trying to locate an element with id invalidelement on website page. When the element is not found, the application throws NoSuchElementException.

Solution: Make sure that the locator (XPath/Id) provided is correct or try to use the explicit wait methods for the presence of element and then perform the action on it. For example,

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfElementLocated(By.id(“invalidelement”)));

ElementNotVisibleException

     ElementNotVisibleException is thrown when WebDriver tries to perform an action on an invisible web element, which cannot be interacted with since element is in a hidden state. For example, there is no button displayed on the web page and if there is HTML code related to the button, then on trying to click on that particular button using locators in the automation script and we will get ElementNotVisibleException. These exception can happen even if the page has not loaded completely and when user tries to interact with an element.

Solution: We have to wait until that particular element becomes visible on web page. To tackle this you can use the explicit wait methods in Selenium. For example,

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(“invisibleElement”));

NoSuchFrameException

     On the webpage, user may have to deal with HTML documents that are embedded inside another HTML document which are called as iframe. In order to work with the web elements on any iframe, we have to first switch to that particular iframe in Selenium by using frame-name or frame-ID and then inspect and locate the respective web elements inside the iframe. NoSuchFrameException occurs, when the driver in the Selenium script is unable to find the frame on the web page to switch which happens when the driver is switching to an invalid or non-existing iframe.

Solution: We have to wait until that particular frame to be available on web page. To tackle this, you can use the explicit wait methods in Selenium. For example,

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.frameToBeAvaliableAndSwitchToIt(frame_id));

NoAlertPresentException

     Alert is a pop-up which provide important information to users or asking for perform certain operation like reading the messages on the alerts or accepting the alert by pressing OK button on the alert or dismissing the alert by pressing CANCEL button etc. In order to work with Alert pop-ups, we have to first switch to Alert and then perform operations on Alert window. NoAlertPresentException occurs when the driver in the script is unable to find the Alert on the web page to switch when the driver is switching to an invalid or non-existing Alert pop-up. Sometime NoAlertPresentException exception is thrown even if the alert is not loaded completely.

Solution: To handle NoAlertPresentException include the script inside try-catch block and provide explicit wait for the alert to be available as shown below.

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.alertIsPresent());

NoSuchWindowException

     We know that Selenium automates Web applications only, and in real time we may have to deal with browser windows which will be opened when you click on buttons or links. In order to interact with the Web Elements on any browser pop-up window, we have to handle all the opened windows and then locate the respective web elements inside the pop-up window. NoSuchWindowException occurs when the driver in the script is unable to find the pop-up window on the web page to switch. NoSuchWindowException is thrown if the window handle doesn’t exist or is not available to switch.

Solution: We would iterate through all the active windows handles and perform the desired actions. For example,

for(String handle: driver.getWindowHandles()) {
try {
driver.switchTo().window(handle);
} catch (NoSuchWindowException e) {
System.out.println(“No such window exceptional case”);
}
}

TimeoutException

     Waits are mainly used in WebDriver to avoid the exception like ElementNotVisibleException which occurs while trying to click on a button before the page is completely loaded. This exception occurs when a command takes more than the wait time completion. However, if the components doesn’t load even after the wait time mentioned, the exception org.openqa.selenium.Timeoutexception will be thrown.

Solution: To avoid this exception, waits commands are added either implicit, explicit or fluent wait.

Implicit Wait:

     The Implicit Wait in Selenium is used to tell the web driver to wait for a certain amount of time before it throws a NoSuchElementException. The default setting is 0. Once we set the time, the web driver will wait for the element for that time before throwing an exception. For example,

driver.manage().timeouts().implicitlyWait(15,TimeUnit.SECONDS) ;
driver.get(“https://journeyofquality.com/ “);

     In the above code, an implicit wait of 15 seconds is added. If the page https://journeyofquality.com/ doesn’t load in 15 seconds, then TimeoutException will be thrown.

Explicit Wait:

     The Explicit Wait in Selenium is used to tell the Web Driver to wait for certain conditions (Expected Conditions) or maximum time exceeded before throwing ElementNotVisibleException exception. It is an intelligent kind of wait, but it can be applied only for specified elements. We already discussed few examples above related to explicit wait like,

wait.until(ExpectedConditions.presenceOfElementLocated(By.id(“webElement”)));
wait.until(ExpectedConditions.frameToBeAvaliableAndSwitchToIt(frame_id));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(“invisibleElement”))
;

Fluent Wait:

     The Fluent Wait in Selenium is used to define maximum time for the web driver to wait for a condition, as well as the frequency with which we want to check the condition before throwing an ElementNotVisibleException exception. It checks for the web element at regular intervals until the object is found or timeout happens. Frequency is setting up a repeat cycle with the time frame to verify or check the condition at the regular interval of time. Below is the sample implmentaion for fluent wait,

Wait wait = new FluentWait(WebDriver driver)
.withTimeout(Duration.ofSeconds(SECONDS))
.pollingEvery(Duration.ofSeconds(SECONDS))
.ignoring(Exception.class);

Overall Exception Handling Solutions

     In order to handle these above types of Selenium exceptions, we will use following exception handling mechanism,

Throw: Throw keyword is used to throw exception to the runtime to handle it.

public static void anyMethod() throws Exception{
try{
// write your code here
}catch (Exception e){
// Do whatever you wish to do here
// Now throw the exception back to the system
throw(e);
}
}

Multiple Catch Blocks: You can use multiple catch() blocks to catch different types of exception. The syntax for multiple catch blocks looks like the following:

public static void anyMethod() throws Exception{
try{
// write your code here
}catch(ExceptionType1 e1){
//Code for Handling the Exception 1
}catch(ExceptionType2 e2){
//Code for Handling the Exception 2
}

Try/Catch: A try block encloses code that can potentially throw an exception. A catch() block contains exception-handling logic for exceptions thrown in a try block. Code within a try/catch block is referred to as protected code, and the syntax for using try/catch looks like the following:

public static void anyMethod() throws Exception{
try{
// write your code here
}catch(Exception e){
//Code for Handling the Exception
}
}

Finally: A finally block contains code that must be executed whether an exception is thrown or not:

public static void anyMethod() throws Exception{
try{
// write your code here
}catch(ExceptionType1 e1){
//Code for Handling the Exception 1
}catch(ExceptionType2 e2){
//Code for Handling the Exception 2
}
finally{
//The finally block always executes.
}
}

     I hope you got an idea on various common selenium exceptions, the solutions and the general way to handle those exceptions. Try to implement these exception handling mechanism in your automation script and handle these runtime anomalies.

make it perfect!

Writing Resilient Test Code

     Ideally, you should be able to write your tests once and run them across all supported browsers. While this is a rosy proposition, there is some work to make this a reliable success. And sometimes there may be a hack or two involved. But the length you must go really depends on the browsers you care about and the functionality you’re dealing with in your application.

     By using high quality locators we’re already in good shape, but there are still some issues to deal with.  This is especially true when working with dynamic, JavaScript heavy pages (which is more the rule than the exception in a majority of web applications you’ll deal with).

     But there is a simple approach that makes up the bedrock of reliable and resilient Selenium tests — and that’s how you wait and interact with elements. Gone are the days of waiting for the page to finish loading, or hard-coding sleeps, or doing a blanket wait time (a.k.a. an implicit wait).  Now are the wonder years of waiting for an expected outcome to occur for a specified amount of time. If the outcome occurs before the amount of time specified, then the test will proceed. Otherwise, it will wait the full amount of time specified.

We accomplish this through the use of explicit waits.

An Example

Let’s step through an example that demonstrates this against a dynamic page on the-internet. The functionality is pretty simple — there is a button. When you click it a loading bar appears for 5 seconds, after which it disappears and is replaced with the text Hello World!

Part 1: Create A New Page Object And Update The Base Page Object

Here’s the markup from the page.

Capture

        At a glance it’s simple enough to tell that there are unique id attributes that we can use to find and click on the start button and verify the finish text.

        When writing automation for new functionality like this, you may find it easier to write the test first (to get it working how you’d like) and then create a page object for it (pulling out the behavior and locators from your test). There’s no right or wrong answer here. Do what feels intuitive to you. But for this example, we’ll create the page object first, and then write the test.

Let’s create a new page object file called DynamicLoading.java in thepageobjects package.

Capture

     In this file we’ll establish inheritance to the base page object and specify the locators and behavior we’ll want to use.

Capture1

     Since there are two examples to choose from we created the methodloadExample which accepts a String of the example number we want to visit as an argument. And similar to our login page object, we have a display check for the finish text (e.g., finishTextPresent()). This check is slightly different though. Aside from the different name, it has a second argument (an integer value of 10). This second argument is how we’ll specify how long we’d like Selenium to wait for an element to be displayed before giving up.

     Let’s update our base page object to enable explicit waits, adding this newwaitForIsDisplayed method to use them.

Capture

     Selenium comes with a wait function which we wrap in a private method (e.g.,private void waitFor) for reuse in this class.

     This method accepts two arguments — the condition we want to wait for (e.g.,ExpectedCondition<WebElement>) and the amount of time we want Selenium to keep checking for (e.g., Integer timeout). If a null value is passed as an argument for the timeout, then the wait time is set to 5seconds. This is handled by a ternary operator (e.g., timeout = timeout != null ? timeout : 5;).

     The waitForIsDisplayed method has two parameters — one for a locator, another for the timeout. Inside the method we call waitFor and send it anExpectedCondition to check for the visibility of an element (e.g.,.visibilityOfElementLocated(locator)). This is similar to our previous display check, but it uses a different Selenium API function that will work with the explicit waits function. You can see a full list of      Selenium’sExpectedConditions here. Unfortunately, this function doesn’t return a Boolean, so we provide one . If the condition is not met by Selenium in the amount of time provided, it will throw a timeout exception. When that happens, we catch it and return false. Otherwise, we return true.

     It’s worth noting that the second parameter is optional when callingwaitForIsDisplayed (e.g., Integer… timeout). If a timeout value is specified, it will get passed to the waitFor method. If nothing is specified,nullwill get passed instead. This gives us the freedom to call this method in our page objects without specifying a timeout (e.g.,waitForIsDisplayed(locator)) or with a timeout (e.g.,waitForIsDisplayed(locator, 20)`).

More on Explicit Waits

     In our page object when we’re using waitForIsDisplayed(finishText, 10) we are telling Selenium to check if the finish text is visible on the page repeatedly. It will keep checking until either the element is displayed or reaches ten seconds — whichever comes first.

     It’s important to set a reasonably sized default timeout for the explicit wait method. But you want to be careful not to make it too high. Otherwise you can run into similar timing issues you get from an implicit wait. But set it too low and your tests will be brittle, forcing you to run down trivial and transient issues.

     The major benefit of explicit waits is that if the behavior on the page takes longer than we expect (e.g., due to slow load times, or a feature change), we can simply adjust this one wait time to fix the test — rather than increase a blanket wait time (which impacts every test). And since the wait is dynamic (e.g., constantly polling), it won’t take the full amount of time to complete (like a static sleep would).

     If you’re thinking about mixing explicit waits with an implicit wait — don’t. If you use both together, you’re going to run into issues later on due to inconsistent implementations of implicit wait across local and remote browser drivers. Long story short, you’ll see inconsistent and odd test behavior.

Part 2: Write A Test To Use The New Page Object

     Now that we have our new page object and an updated base page, it’s time to write our test to use it.

     Let’s create a new file called TestDynamicLoading.java in the testspackage.

Capture

     The contents of this test file are similar to TestLogin with regards to the imported classes and the setUp/tearDown methods.

Capture1

     In our test (e.g., public void hiddenElementLoads()) we are visiting the first dynamic loading example and clicking the start button (which is accomplished in dynamicLoading.loadExample(“1”)). We’re then asserting that the finish text gets rendered.

     When we save this and run it (mvn clean test -Dtest=TestDynamicLoading from the command-line) it will run, wait for the loading bar to complete, and pass.

Part 3: Update Page Object And Add A New Test

     Let’s step through one example to see if our explicit wait approach holds up.

     The second dynamic loading example is laid out similarly to the last one. The only difference is that it renders the final text after the progress bar completes (whereas the previous example had the text on the page but it was hidden).

Here’s the markup for it.

Capture

     In order to find the selector for the finish text element we need to inspect the page after the loading bar sequence finishes. Here’s what it looks like.

Capture

     Let’s add a second test to TestDynamicLoading.java calledelementAppears() that will load this second example and perform the same check as we did for the previous test.

Capture

     When we run both tests (mvn clean test -Dtests=TestDynamicLoading from the command-line) we will see that the same approach will work for both cases.

Browser Timing

     Using explicit waits gets you pretty far. But there are a few things you’ll want to think about when it comes to writing your tests to work against various browsers.

     It’s simple enough to write your tests locally against Firefox and assume you’re all set. Once you start to run things against other browsers, you may be in for a rude awakening. The first thing you’re likely to run into is the speed of execution. A lot of your tests will start to fail when you point them at either Chrome or Internet Explorer, and likely for different reasons.

     In my experience, Chrome execution is very fast, so you will see some odd timeout failures. This is an indicator that you need to add explicit waits to parts of your page objects that don’t already have them. And the inverse is true when running things against older version of Internet Explorer (e.g., IE 8). This is an indicator that your explicit wait times are not long enough since the browser is taking longer to respond — so your tests timeout.

      The best approach to solve this is an iterative one. Run your tests and find the failures. Take each failed test, adjust your code as needed, and run it against the browsers you care about. Repeat until you make a pass all the way through each of the failed tests. Then run a batch of all your tests to see where they fall down. Repeat until everything’s green.

     Once you’re on the other side of these issues, the amount of effort you need to put into it should diminish dramatically.

Conclusion

      By explicitly waiting to complete an action, our tests are in a much more resilient position because Selenium will keep trying for a reasonable amount of time rather than trying just once. And each action can be tuned to meet the needs of each circumstance. Couple that with the dynamic nature of explicit waits, and you have something that will work in a multitude of circumstances — helping you endure even the toughest of browsers to automate.

     This is one of the most important concepts in testing with Selenium. Use explicits waits often.

Reference

http://elementalselenium.com/