Webdriver FluentWait不会忽略异常

时间:2013-12-09 10:58:23

标签: java selenium-webdriver

我已经通过此页面http://www.efinancialcareers.co.uk/search自动化了一些用户流程。 当我使用左侧精炼轨道缩小搜索范围时,会出现一个叠加层,用户必须等到返回搜索结果。该方法等待叠加层出现,然后等待它消失。

public void waitForSRPOverlayToComplete() {

    Wait<WebDriver> wait = new FluentWait<WebDriver>(getDriver())
            .withTimeout(5, TimeUnit.SECONDS)
            .pollingEvery(1, TimeUnit.NANOSECONDS)
            .ignoring(NoSuchElementException.class)
            .ignoring(TimeoutException.class);

    **// Error occurs here**
    WebElement blockedOverlay = wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            return driver.findElement(By.className("blockOverlay"));
        }
    });

    Wait<WebDriver> wait2 = new FluentWait<WebDriver>(getDriver())
            .withTimeout(5, TimeUnit.SECONDS)
            .pollingEvery(1, TimeUnit.NANOSECONDS)
            .ignoring(NoSuchElementException.class)
            .ignoring(TimeoutException.class);

    wait2.until(ExpectedConditions.stalenessOf(blockedOverlay));
}

有时我会收到Timeout异常,因为找不到元素(blockOverlay)。当发生这种情况并且叠加确实出现时我观察了页面,但我认为有时当搜索速度非常快时,上面的方法会错过它。 我不明白为什么我会遇到技术错误,因为我告诉流利的等待忽略它们。

这是显示叠加层的代码:

$('body').block({
            message: $('#loaderEl'),
            css: {
                backgroundColor: 'transparent',
                border: "none",
                color: '#333333',
                fontWeight: 'bolder',
                top: ($(window).height() - $('#loaderEl').height()) / 2 + $(window).scrollTop() + "px"
            },
            overlayCSS: {
                backgroundColor: '#f8f8f8'
            },
            centerY: false
        });

并将其删除

$('body').unblock();

这是我收到的错误:

Caused by: org.openqa.selenium.TimeoutException: Timed out after 5 seconds waiting for     com.efinancialcareers.myefc.desktop.BasePage$6@548238e0
Build info: version: '2.35.0', revision: '8df0c6bedf70ff9f22c647788f9fe9c8d22210e2',     time: '2013-08-17 12:46:41'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_26'
Driver info: driver.version: unknown
    ... 33 more
Caused by: org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"class name","selector":"blockOverlay"}

任何帮助或建议都将不胜感激。

2 个答案:

答案 0 :(得分:8)

TimeoutException实际超时时,您无法取消FluentWait。这只是API的本质。如果这是您真正想要忽略的异常,则需要捕获TimeoutException

此外,作为旁注,尝试每纳秒轮询一次这种情况可能会适得其反。您应该将轮询间隔延长到每200或250毫秒。

答案 1 :(得分:1)

非常感谢Jim Evans给我的关键线索,我需要知道为什么会出现这个问题。

我决定进一步深入研究FluentWait代码(Java 1.8或更高版本),看看为什么抛出TimeoutException,即使你请求它不被抛出。

FluentWait的典型示例:

        WebDriver driver = new ChromeDriver();

        FluentWait wait = new FluentWait(driver)
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class);

        WebElement foo = (WebElement) wait.until(new Function() {
            @Override
            public WebElement apply(Object input) {
                return null;
            }
        });

我们查看FluentWait的until方法,因为这是实际启动等待过程的方法。很可能所有异常处理/抛出逻辑都存在。 FluentWait的所有其他方法调用,例如withTimeoutignoring等实际上为FluentWait对象创建“设置”。它们不执行任何操作,如等待或运行某些代码等。

让我们看一下documentation for "until"。最后一行告诉我们该方法抛出TimeoutException。因此,即使您请求了,也不应该忽略TimeoutException。

Throws:
TimeoutException - If the timeout expires.

我们现在快速查看FluentWait的代码,以了解为什么“until”不会忽略TimeoutException。

  public <V> V until(Function<? super T, V> isTrue) {
    long end = clock.laterBy(timeout.in(MILLISECONDS));
    Throwable lastException = null;
    while (true) {
      try {
        V value = isTrue.apply(input);
        if (value != null && Boolean.class.equals(value.getClass())) {
          if (Boolean.TRUE.equals(value)) {
            return value;
          }
        } else if (value != null) {
          return value;
        }
      } catch (Throwable e) {
        lastException = propagateIfNotIgnored(e);
      }

      // Check the timeout after evaluating the function to ensure conditions
      // with a zero timeout can succeed.
      if (!clock.isNowBefore(end)) {
        String message = messageSupplier != null ?
            messageSupplier.get() : null;

        String toAppend = message == null ?
            " waiting for " + isTrue.toString() : ": " + message;

        String timeoutMessage = String.format("Timed out after %d seconds%s",
            timeout.in(SECONDS), toAppend);
        throw timeoutException(timeoutMessage, lastException);
      }

      try {
        sleeper.sleep(interval);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new WebDriverException(e);
      }
    }
  }

while块将:

  1. 返回“value”变量,或者
  2. 传播您未请求忽略的任何异常。 (请参阅propagateIfNotIgnored方法调用。该名称使其显而易见,您也可以看到代码以进行确认。)
  3. if块将在未传播异常时运行。如果发生超时,它将抛出TimeoutException。所以,这是负责超时异常的代码。

相关问题