Waiting in C# WebDriver

Waiting in WebDriver is the area where I see most teams struggle in writing maintainable/efficient Selenium WebDriver tests, especially with pages that contain a lot of JavaScript and AJAX to dynamically display content. Here I’ll outline some of the waiting approaches and outline which is best to use in different circumstances.

Background

WebDriver by default waits until the page is loaded (using the onload JavaScript event) before it tries to execute commands. If you have content that loads after page load then you’ll need to use an additional form of waiting.

WebDriver offers two styles of waiting: implicit and explicit.

Implicit Waiting

Implicit, or implied waiting involves setting a configuration timeout on the driver object where it will automatically wait up to this amount of time before throwing a NoSuchElementException.

The benefit of implicit waiting is that you don’t need to write code in multiple places to wait as it does it automatically for you.

The downsides to implicit waiting include unnecessary waiting when doing negative existence assertions and having tests that are slow to fail when a true failure occurs (opposite of ‘fail fast’).

Another consideration is that Even if you set an lower implicit wait, there may be places in your web application where you’ll need a longer explicit wait so it’s hard to use implicit waits exclusively unless you set it at a high value, which is problematic for reasons mentioned above.

Explicit Waiting

Explicit waiting involves putting explicit waiting code in your tests in areas where you know that it will take some time for an element to appear/disappear or change.

The most basic form of explicit waiting is putting a sleep statement in your WebDriver code. This should be avoided at all costs as it will always sleep and easily blow out test execution times.

WebDriver provides a WebDriverWait class which allows you to wait for an element in your code. For example, using the ElementIsPresent extension method I previously wrote about we can do this:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("data:text/html,<script> var timer; function startCount() { timer=setInterval(count,1000); } function count() { var e=document.getElementById('counter'); var newVal=parseFloat(e.innerHTML)+1;e.innerHTML=newVal; e.className=\"c\"+newVal;}</script><body onload=\"startCount();\"><div id=\"counter\">1</div></body>");
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
Assert.AreEqual(true, wait.Until(d => d.ElementIsPresent(By.ClassName("c2"))));
Assert.AreEqual(true, wait.Until(d => !d.ElementIsPresent(By.ClassName("c2"))));

You can easily write an extension method that makes it easy to call something like WaitUntilElementIsPresent instead of creating creating new WebDriverWait classes constantly.

public static bool WaitUntilElementIsPresent(this IWebDriver driver, By by, int timeout=10)
{
    var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeout));
    return wait.Until(d => d.ElementIsPresent(by));
}

The one issue with using the WebDriverWait class it you can’t use it without throwing an exception when it doesn’t succeed. If you wish to wait without throwing an exception then it is trivial to write your own extension method to do the waiting/polling, such as:

public static bool WaitUntilElementIsPresent(this IWebDriver driver, By by, int timeout=10)
{
    for (var i = 0; i < timeout; i++)
    {
        if (driver.ElementIsPresent(by)) return true;
        Thread.Sleep(1000);
    }
    return false;
}

Recommendations

I suggest you set a small (1 or 2 seconds) implicit wait for your WebDriver code, but ensure that you disable it for any immediate checks, such as if you use an ElementIsPresent method. This way you get free automatic simple waiting with the ability for your tests to still fail fast.

I suggest you add explicit waits in places where it consistently takes longer than this time for an element to appear or disappear. You can easily write some WebDriver extension methods that abstract your wait code so that it is simple to call explicit waits from the driver object itself. That gives the added benefit of having a common explicit waiting approach across your code which you could change if you need to in the future.

3 thoughts on “Waiting in C# WebDriver

  1. Nice post, Alister and totally agree. Waiting in Selenium can be painful at first. Do you find C# bindings to be especially problematic?

  2. I like Watir myself, though I’ve not been on a project that’s used it. I’m currently using, and liking, Geb/Groovy on top of Webdriver. Great selectors and nice page objects. Groovy itself is a fine language.

Comments are closed.