9

有时在关闭 Javascript 的情况下在 WebDriver 上运行测试时,WebDriver 在找到元素并尝试单击它时会由于 ElementNotFound 错误而崩溃。

但是,元素显然存在!

阅读后:http ://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_My_XPath_finds_elements_in_one_browser,_but_not_in_others._Wh

我得出的结论是 webdriver 一定不能等到网页完成加载。如何使用 Webdriver 等待类?有人可以提供一个例子吗?

4

3 回答 3

18

此示例发布在 Google Groups 上。根据谷歌开发者的说法:

1 使用隐式等待。在这里,驱动程序将一直等到指定的超时时间,直到找到元素。请务必阅读 javadoc 中的注意事项。用法:

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 使用org.openqa.selenium.support.ui.WebDriverWait类。这将轮询直到预期的条件为真,返回该条件的结果(如果它正在寻找一个元素)。这比隐式等待灵活得多,因为您可以定义任何自定义行为。用法:

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"));
于 2010-11-10T22:07:13.147 回答
3

将 nilesh 的回答更进一步,您还可以通过使用 SearchContext 接口允许更精细的搜索(例如,在 WebElement 的上下文中):

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

执行由 FluentWait<SearchContext> 实例(而不是 WebDriverWait)执行。通过将其执行和必要的异常处理包装在一个实用方法中,给自己一个漂亮的编程接口(PageObject类型层次结构的根是一个好地方):

/**
 * @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

示例用法:

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
    }
}
于 2011-06-30T00:58:31.157 回答
0

Fluent Wait - 最好的方法,因为它是最灵活和可动态配置的(具有忽略异常选项,轮询每个,超时):

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

像这样使用:

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

显式等待FluentWait- 好吧,它与预配置的等待类型相同,但具有pollingEvery等待类型,例如FluentWait<WebDriver>(使用更快):

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

ImplicitWait - 不推荐,因为它为您的所有会话配置一次。这也用于每个查找元素并仅等待存在(不等ExpectedConditions...):

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
于 2016-11-20T15:40:07.867 回答