WebDriver Selenium API: ElementNotFoundErrorException when Element is clearly there !

StackOverflow https://stackoverflow.com/questions/4112180

  •  29-09-2019
  •  | 
  •  

Question

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 ?

Was it helpful?

Solution

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"));

OTHER TIPS

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
    }
}

Fluent Wait - Best approach as it's the most flexible and configurable on the fly (has ignore exceptions option, polling every, timeout):

public Wait<WebDriver> getFluentWait() {
    return new FluentWait<>(this.driver)
            .withTimeout(driverTimeoutSeconds, TimeUnit.SECONDS)
            .pollingEvery(500, TimeUnit.MILLISECONDS)
            .ignoring(StaleElementReferenceException.class)
            .ignoring(NoSuchElementException.class)
            .ignoring(ElementNotVisibleException.class)
}

Use like so:

WebElement webElement = getFluentWait().until(x -> { return driver.findElement(elementBy); } );

Explicit Wait - Well it's the same as FluentWait but with pre-configured pollingEvery and the type of Wait e.g. FluentWait<WebDriver> (faster to use):

WebDriverWait wait = new WebDriverWait(driver, 30000);
WebElement item = wait.until(ExpectedConditions.visibilityOfElementLocated(yourBy));

ImplicitWait - Not recommended as it is configured once for all your session. This also is used for every find element and waits for presence only (no ExpectedConditions etc...):

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top