如何避免 Selenium 中的“StaleElementReferenceException”?

新手上路,请多包涵

我正在使用 Java 实施大量 Selenium 测试 - 有时,我的测试由于 StaleElementReferenceException 而失败。

您能否建议一些使测试更稳定的方法?

原文由 hoang nguyen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 771
2 个回答

如果页面上发生的 DOM 操作暂时导致元素不可访问,就会发生这种情况。为了允许这些情况,您可以在最终抛出异常之前尝试在循环中多次访问该元素。

试试 这个来自 darrelgrainger.blogspot.com 的出色解决方案

 public boolean retryingFindClick(By by) {
    boolean result = false;
    int attempts = 0;
    while(attempts < 2) {
        try {
            driver.findElement(by).click();
            result = true;
            break;
        } catch(StaleElementException e) {
        }
        attempts++;
    }
    return result;
}

原文由 jspcal 发布,翻译遵循 CC BY-SA 3.0 许可协议

我间歇性地遇到这个问题。我不知道的是,BackboneJS 在页面上运行并替换了我试图单击的元素。我的代码看起来像这样。

 driver.findElement(By.id("checkoutLink")).click();

这当然在功能上与此相同。

 WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
checkoutLink.click();

偶尔会发生的是 javascript 会在查找和单击之间替换 checkoutLink 元素,即。

 WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
// javascript replaces checkoutLink
checkoutLink.click();

尝试单击链接时,这理所当然地导致了 StaleElementReferenceException。我找不到任何可靠的方法来告诉 WebDriver 等到 javascript 完成运行,所以这就是我最终解决它的方法。

 new WebDriverWait(driver, timeout)
    .ignoring(StaleElementReferenceException.class)
    .until(new Predicate<WebDriver>() {
        @Override
        public boolean apply(@Nullable WebDriver driver) {
            driver.findElement(By.id("checkoutLink")).click();
            return true;
        }
    });

此代码将不断尝试单击链接,忽略 StaleElementReferenceExceptions,直到单击成功或达到超时。我喜欢这个解决方案,因为它使您不必编写任何重试逻辑,并且仅使用 WebDriver 的内置结构。

原文由 Kenny 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题