Using wrapper methods for better error handling in Selenium

Frequent users of Selenium WebDriver might have come across the problem that when they’re using Selenium for testing responsive, dynamic web applications, timing and synchronization can be a major hurdle in creating useful and reliable automated tests. In my current project, I’m creating WebDriver-based automated tests for a web application that heavily relies on Javascript for page rendering and content retrieval and display, which makes waiting for the right element to be visible, clickable or whatever state it needs to be in significantly less than trivial.

Using the standard Selenium methods such as click() and sendKeys() directly in my script often results in failures as a result of the weg page element being invisible, disabled or reloaded (this last example resulting in a StaleElementReferenceException). Even using implicit waits when creating the WebDriver object didn’t always lead to stable tests, and I refuse to use Thread.sleep() (and so should you!). Also, I didn’t want to use individual WebDriverWait calls for every single object that needed to be waited on, since that introduces a lot of extra code that needs to be maintained. So I knew I had to do something more intelligent for my tests to be reliable – and therefore valuable as opposed to a waste of time and money.

Wrapper methods
The solution to this problem lies in using wrapper methods for the standard Selenium methods. So instead of doing this every time I need to perform a click:

(new WebDriverWait(driver, 10)).until(ExpectedConditions.elementToBeClickable(By.id("loginButton")));
driver.findElement(By.id("loginButton")).click();

I have created a wrapper method click() in a MyElements class that looks like this:

public static void click(WebDriver driver, By by) {
	(new WebDriverWait(driver, 10)).until(ExpectedConditions.elementToBeClickable(by));
	driver.findElement(by).click();
}

Of course, the 10 second timeout is arbitrary and it’s better to replace this with some constant value. Now, every time I want to perform a click in my test I can simply call:

MyElements.click(driver, By.id("loginButton");

which automatically performs a WebDriverWait, resulting in much stabler, better readable and maintainable scripts.

Extending your wrapper methods: error handling
Using wrapper methods for Selenium calls has the additional benefit of making error handling much more generic as well. For example, if you often encounter a StaleElementReferenceException (which those of you writing tests for responsive and dynamic web applications might be all too familiar with), you can simply handle this in your wrapper method and be done with it once and for all:

public static void click(WebDriver driver, By by) {
	try {
		(new WebDriverWait(driver, 10)).until(ExpectedConditions.elementToBeClickable(by));
		driver.findElement(by).click();
	catch (StaleElementReferenceException sere) {
		// simply retry finding the element in the refreshed DOM
		driver.findElement(by).click();
	}
}

This is essentially my own version of this excellent solution for handling a StaleElementReferenceException. By using wrapper methods, you can easily handle any type of exception in its own specific way, which will improve your tests significantly.

Extending your wrapper methods: logging
Your wrapper methods also allow for better logging capabilities. For example, if you’re using the ExtentReports library for creating HTML reports for Selenium tests (as I do in my current project), you can create a log entry every time an object is not clickable after the WebDriverWait times out:

public static void click(WebDriver driver, By by) {
	try {
		(new WebDriverWait(driver, 10)).until(ExpectedConditions.elementToBeClickable(by));
		driver.findElement(by).click();
	catch (StaleElementReferenceException sere) {
		// simply retry finding the element in the refreshed DOM
		driver.findElement(by).click();
	}
	catch (TimeoutException toe) {
		test.log(logStatus.Error, "Element identified by " + by.toString() + " was not clickable after 10 seconds");
	}
}

Here, test is the ExtentTest object representing the log for the current test. See how easy this is?

Other possible benefits
There’s a couple of other benefits to using these wrapper methods, some of which I use in my current project as well, such as:

  • Automatically failing the JUnit / TestNG (or in my case NUnit) test whenever a specific error occurs by including an Assert.Fail();
  • Restoring or recreating specific conditions or a specific application state after an error occurs to prepare for the next test (e.g. ending the current user session)
  • Automatically restarting a test in case of a specific error

And I’m sure there are many more.

Wrapping this up (pun intended!), using these wrapper methods for standard Selenium calls can be very beneficial to your Selenium experience and those of your clients or employers. They certainly saved me a lot of unnecessary code and frustration over brittle tests..

29 thoughts on “Using wrapper methods for better error handling in Selenium

  1. Hi Bas,

    I just came across your article and has lots of information. Recently I took up the task of automating my application using Selenium webdriver and was able to automate about 200+ test cases using a small framework using testng and maven. During my automation i encountered a common problem with element not visible. I did try many ways like thread.sleep and all. It never was stable. That’s when i did some research and came across a way it worked. Please find the approach I followed:

    boolean t=false;
    int c=0;
    int i=0;
    while (c=1){
    driver.findElement(By.xpath(“xpath”)).click();
    }
    if(i==25){
    break;
    }
    i++;
    }

    So the good news is that we don’t need to mention a timer and set the value of i to any value. If at all the element is not found it would hit the break and would fail. Hope this information helps.

    • Sorry the code posted had errors, Please find the corrected one

      boolean t=false;
      int c=0;
      int i=0;

      while (t!=true){

      int c=driver.findElement(By.xpath(“xpath”)).size();
      if(c>=1)
      {
      driver.findElement(By.xpath(“xpath”)).click();
      t=true;
      }
      if(i==25){
      break;
      }
      i++;
      }

    • Hi Rexi,

      thanks for your comment. I don’t understand why you would want to use the code you used when the ExpectedConditions.elementToBeClickable (or any other ExpectedConditions invariant) does that exactly for you. It polls the DOM of your page until the specified ExpectedCondition is met, or until the timeout has been reached, in which case it throws a WebDriverTimeoutException. Whichever comes first.

      I normally specify the timeout value in a constant somewhere else, by the way, I only specified it here directly because it’s more readable this way.

  2. Thank you Bas for the reply, I was encountering this issue and did not get a solution. The Explicit wait with elementToBeClickable was not thought about me. That’s when I tried to solve it using the code I posted. It worked. Would try the solution you had provided. Thought to share my experience. Nice post and looking forward to see more valuable information. Thank you!

  3. Pingback: Testing Bits – 12/27/15 – 1/2/16 | Testing Curator Blog

  4. Pingback: Java Testing Weekly 1 / 2016

  5. Bas i resigned.That really takes a toll on you if you had a very good friendship with your fellow employees right?
    Anyway if you know any good websites which has good interview questions on selenium webdriver suggest me ok?we both know what i know about selenium webdriver is not enough,but i think i should give it a try by attending some interviews and understand what they really want and then proceed right?

    • Hi Sherin,

      Good luck on your quest for a better job! As I’ve never had a job interview where we went really in depth on Selenium knowledge (or any tool for that matter) I can’t help you with those interview questions but I’ve seen some lists come by on the Internet, so a quick Google search should help you out.

  6. Hi Bas,

    Iam new for selenium,i want to use scroll option in my current work can u pls guide me with that..its very useful for me.I tried in google but not able find proper way for my needs

    Thanks

    • Hi Kalyan,

      scrolling in Selenium can be a bit tricky, but there are various options to make it work. Here are some suggestions, but it’s very hard to give a 100% working answer without having access to your application.

      There’s also the Actions class which has a MoveToElement method that you can use to move to elements that are not currently displayed / in view

  7. Hi Bas,
    These days python is being extensively with Selenium. Would you be able to share some posts regarding test automation using selenium python, especially designing a framework using selenium python.

    Thanks
    Rajat

    • Hi Rajat,

      That’s probably not going to happen, for three reasons:

      1. I pretty much stopped writing technical posts on Selenium
      2. I don’t think using Python is any different from any other language when it comes to Selenium
      3. I don’t ‘design’ ‘frameworks’, I ‘build’ ‘solutions’. It’s impossible to create a fitting solution if you don’t know what the problem is, which is why I am very skeptical about the added value of generic frameworks

      I’m sure there are lots of other web sites that can help you out, though.

      • I do have to thank you though, point 3. has made me think of something I’ll be writing another blog post on soon enough.

        • Thanks Bas…
          Recently I was listening to a podcast about test automation and it suggested automation testers to either user ruby or python. Also, since python is so much in demand these days, made me ask you about using it with selenium.

          Apart from this, there is a problem that I want to discuss. In my AUT, there are lots of database calls for each text boxes(on typing something in text boxes, suggestions gets displayed to the user). Now I want my script to wait for that db call to finish and then selecting the value.I am aware of the method wait for element to be invisible etc. but to implement it I need to have a locator for that loading image that appears whenever there is a db call. Since the db calls is for 1-2 secs, I am not able to get the locator of the loading image using browser inspector. Could you please help me in tackling this problem? Also, if you have some suggestions in tacking such kind of issues in a better way, request you to let me know.

          Thanks
          Rajat

  8. Hi Bas.

    Is there a way by which we can handle StaleElement Exception.This exception is coming intermittently and for any element it may come.
    I am looking for a way such that whenever this exception comes my code should re-run again for the same element.

    Thanks
    RK

    • Hey RK,

      if you’re using wrappers this is actually pretty simple: just catch the StaleElementReferenceException and do the findElement (and any possible action that follows it) again.

  9. Instead of directly calling WebDriver methods, Is it more beneficial to abstract WebDriver inside class and expose it’s methods through it’s class?

    • In most cases, the answer will be yes. I especially like using these wrappers (call it abstraction if you want) because you can do a lot of error handling and additional logging in a centralized and therefore easy to maintain manner.

  10. Dear Bas,

    Its really nice article.
    Could you please suggest how to implement this if one is using PageFactory annotation for identifier strategy? Also how to implement something similar to this for Appium

    Many thanks

    • Hey Laxmi,

      for Appium I think you can do something very similar, simply by passing your Appium driver object instead of the default Chrome or Firefox driver object. Exception handling might work a little different though (different exceptions that are thrown), I’ve never worked with Appium before so I don’t know for sure.

      As for using PageFactory, that would be a little harder. One thing you could do is instead of passing the By object to the wrapper method, pass the WebElement method and perform the action and catch exceptions accordingly. I don’t really see the use of PageFactory, so I tend to not use it, but you can try.

  11. Hi All,

    I am getting InvocationTargetException in catch block of

    invoker.class while running selenium script with TestNG.

    and due to this not able to move next steps can some one help here will be appreciable.

    Thanks,

  12. Pingback: The Anatomy of a Comprehensive Selenium Testing Strategy | CrossBrowserTesting.com

Leave a Reply

Your email address will not be published. Required fields are marked *