2

据我了解,只有在代码对实例进行操作时才会引发此类异常WebElement,并在重新加载或删除相应的 DOM 元素后对其调用方法。

因此,为了确定是否可以抛出该异常,我在接口实现RemoteWebDriver.findElements(By)的源代码中寻找了那种代码(in )。但是,深入到's 代码中的调用堆栈最终对我来说变得太难了。RemoteWebDriverWebDriverselenium-remote-driver-3.8.1.jarRemoteWebDriver

所以我的问题是:除了试图通过检查 Selenium 源来弄清楚这一点之外,还有没有更好的方法来判断一个WebDriver方法是否findElements(By)能够抛出StaleElementReferenceException?它是一个RuntimeException,而 Selenium JavaDoc 没有@throws它。

4

2 回答 2

2

您指出了有关“StaleElementReferenceException”的问题,这与 webElement 实例更改时有关,当 DOM 由于页面上的某些活动而更改时。

它与 WebDriver 如何在内部处理对 webElements 的引用有关,并且在运行时对对象的引用发生更改时会发生此问题。

现在,让我们假设当您获取元素并且在对其执行任何操作之前,您的页面上刷新了一些内容。它可能是正在刷新的整个页面,也可能是某个调用仅刷新了元素所在的 DOM 的一部分。

在这种情况下,WebDriver 使用并存储在缓存中某处的内部 id 已经过时(不再引用),所以现在对于这个 WebElement 上的每个操作,我们都会得到StaleElementReferenceException.

所以要尽量避免在关键地方使用这种方法,以确定元素是否过时。

public static boolean isStale(WebElement e){
    try{
        e.isDisplayed();
        return false;
    }catch(StaleElementReferenceException ex){
        return true;
    }
}

通常刷新页面、页面对象或仅此特定元素在 90% 的情况下会有所帮助。

并且在刷新页面/元素后,WebDriver 会为这个元素分配一个不同的内部 Id,并且可以再次使用它而不会出现任何问题。

这个问题是 PageObject / PageFactory 设计模式的解决者。

public class SomePage {
    @FindBy(how = How.NAME, using = "q")
    private WebElement searchBox;


    public SomePage() {
        PageFactory.initElements(driver, this);
    }


    public void searchFor(String text) {
        searchBox.sendKeys(text);
    }
}

希望这可以帮助,

于 2018-07-19T10:36:29.603 回答
1

陈旧元素引用异常

StaleElementReferenceException扩展了WebDriverException并指示对元素的引用现在是“陈旧的”并且元素引用不再存在于页面的 DOM 上。


一一回答您的疑问:

  • StaleElementReferenceException只有当代码在 WebElement 实例上运行时才能抛出,在相应的 DOM 元素被重新加载或删除后调用它的方法:你快到了。以下是完整的原因列表:
    • 该元素已被完全删除。
    • 该元素不再附加到 DOM。
    • 元素所在的网页已刷新。
    • (前一个)元素已被JavaScriptAjaxCall删除,并被具有相同ID或其他属性的(新)元素替换。
  • 解决方案如果一个旧元素已被新的相同元素替换,简单的策略是再次使用findElementfindElements寻找该元素。
  • 我在 WebDriver 接口的 RemoteWebDriver 实现的源代码中寻找了这种代码 :从用户级别的角度来看,即使知道算法流程图,它也不会增加任何价值。作为最终用户,您需要清楚地了解实现,这将有助于您交付优化的测试代码
  • 除了试图通过检查 Selenium 源来弄清楚这一点之外,还有更好的方法来判断一个 WebDriver 方法 - 或者特别是 findElements(By) - 是否可以抛出StaleElementReferenceException 没有单一完整的证明方法来预测是否findElement(By)findElements(By)可以通过StaleElementReferenceException或不。如果AUT(被测应用程序)基于JavaScriptAjaxCallsjQuery,则大多数WebElement将是动态的,这就是WebDriverWait在寻找元素之前帮助我们的地方。

参考

以下是本次讨论的参考资料:

于 2018-07-19T12:22:30.703 回答