如何避免硒中的“陈旧元素引用异常”?

2022-08-31 08:46:22

我正在使用Java实现很多Selenium测试 - 有时,由于StaleElementReferenceException,我的测试会失败。

你能建议一些方法使测试更稳定吗?


答案 1

如果页面上发生的 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;
}

答案 2

我间歇性地遇到了这个问题。我不知道,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();

这正确地导致了一个陈旧的ElementReferenceException,当试图点击链接。我找不到任何可靠的方法来告诉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的内置构造。