Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebDriver Selenium API: ElementNotFoundErrorException when Element is clearly there !

Tags:

webdriver

sometimes when running tests on WebDriver with Javascript turned off, WebDriver crashes due to an ElementNotFound Error when it finds an element, and attempts to click it.

However, the element is clearly there !

After reading this : http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_My_XPath_finds_elements_in_one_browser,_but_not_in_others._Wh

I came to the conclusion that webdriver must not be waiting until the web page has completed loaded. How do I use the Webdriver Wait class ? Can someone provide an example ?

like image 896
KJW Avatar asked Nov 06 '10 06:11

KJW


People also ask

How do you wait until an element is clickable on a website?

Wait until the element's . Displayed property is true (which is essentially what visibilityOfElementLocated is checking for). Wait until the element's . Enabled property is true (which is essentially what the elementToBeClickable is checking for).

How do I make Selenium wait for some time?

We can make Selenium wait for 10 seconds. This can be done by using the Thread. sleep method. Here, the wait time (10 seconds) is passed as a parameter to the method.

What is wait command in Selenium?

In automation testing, wait commands direct test execution to pause for a certain length of time before moving onto the next step. This enables WebDriver to check if one or more web elements are present/visible/enriched/clickable, etc.

What is clickable element in Selenium?

To verify, if the element can be clicked, we shall use the elementToBeClickable condition. A timeout exception is thrown if the criteria for the element is not satisfied till the driver wait time.


2 Answers

This example was posted on Google Groups. According to Google developers:

1 Use implicit waits. Here the driver will wait up until the designated timeout until the element is found. Be sure to read the javadoc for the caveats. Usage:

driver.get("http://www.google.com"); 
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); 
WebElement element = driver.findElement(By.name("q")); 
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); 
// continue with test... 

2 Use the org.openqa.selenium.support.ui.WebDriverWait class. This will poll until the expected condition is true, returning that condition's result (if it's looking for an element). This is much more flexible than implicit waits, as you can define any custom behavior. Usage:

Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) { 
  return new Function<WebDriver, WebElement>() { 
    public WebElement apply(WebDriver driver) { 
      return driver.findElement(locator); 
    }
  };
}

// ... 
driver.get("http://www.google.com"); 
WebDriverWait wait = new WebDriverWait(driver, /*seconds=*/3); 
WebElement element = wait.until(presenceOfElementLocated(By.name("q"));
like image 100
nilesh Avatar answered Oct 16 '22 12:10

nilesh


Taking nilesh's answer a step further, you can also allow finer-tuned searches (eg, within the context of a WebElement) by using the SearchContext interface:

Function<SearchContext, WebElement> elementLocated(final By by) {
    return new Function<SearchContext, WebElement>() {
        public WebElement apply(SearchContext context) {
            return context.findElement(by);
        }
    };
}

Execution is performed by a FluentWait<SearchContext> instance (instead of WebDriverWait). Give yourself a nice programming interface by wrapping its execution and necessary exception handling in a utility method (the root of your PageObject type hierarchy is a good spot):

/**
 * @return The element if found before timeout, otherwise null
 */
protected WebElement findElement(SearchContext context, By by,
        long timeoutSeconds, long sleepMilliseconds) {
    @SuppressWarnings("unchecked")
    FluentWait<SearchContext> wait = new FluentWait<SearchContext>(context)
            .withTimeout(timeoutSeconds, TimeUnit.SECONDS)
            .pollingEvery(sleepMilliseconds, TimeUnit.MILLISECONDS)
            .ignoring(NotFoundException.class);
    WebElement element = null;
    try {
        element = wait.until(elementLocated(by));
    }
    catch (TimeoutException te) {
        element = null;
    }
    return element;
}

/**
 * overloaded with defaults for convenience
 */
protected WebElement findElement(SearchContext context, By by) {
    return findElement(context, by, DEFAULT_TIMEOUT, DEFAULT_POLL_SLEEP);
}

static long DEFAULT_TIMEOUT = 3;       // seconds
static long DEFAULT_POLL_SLEEP = 500;  // milliseconds

Example usage:

WebElement div = this.findElement(driver, By.id("resultsContainer"));
if (div != null) {
    asyncSubmit.click();
    WebElement results = this.findElement(div, By.id("results"), 30, 500);
    if (results == null) {
        // handle timeout
    }
}
like image 3
Joe Coder Avatar answered Oct 16 '22 12:10

Joe Coder