Overloading findElement() to add waiting time

Update: 2010-08-05: It looks like overloading findElements() to add a wait time is no longer required. As of version 2.0a5, you can use RemoteWebDriver.RemoteTimeouts.implicitlyWait() like the following:

driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS)


When you run the same test multiple times without changing any code, WebDriver sometimes fails to find elements. This may be caused by multiple factors such as the network connection speed, ajax, etc. For a detailed explanation, see here. Due to these problems, I decided to make findElement() more fault tolerant. Therefore, I overload findElement() to add a waiting time. It will keep waiting until the element is found or a timeout is expired.

/**
 * Before finding the element, keep waiting until the element is found or a timeout is expired.
 * @param webDriver
 * @param by
 * @param timeout Timeout in milliseconds.
 * @return Return the WebElement found.
 */
private WebElement findElement(WebDriver webDriver, By by, int timeout)
{
  int iSleepTime = 1000;
  for(int i=0; i<timeout; i+=iSleepTime)
  {
    List<WebElement> oWebElements = webDriver.findElements(by);
    if(oWebElements.size()>0)
    {
      return oWebElements.get(0);
    }
    else
    {
      try
      {
        Thread.sleep(iSleepTime);
        System.out.println(String.format("%s: Waited for %d milliseconds.[%s]", new java.util.Date().toString(), i+iSleepTime, by));          
      }
      catch(InterruptedException ex) 
      {
        throw new RuntimeException(ex);
      }
    }
  }
 
  // Can't find 'by' element. Therefore throw an exception.
  String sException = String.format("Can't find %s after %d milliseconds.", by, timeout);
  throw new RuntimeException(sException);    
}