我正在尝试学习PageFactory模型。我理解当我们做initElements
时,WebElements就位于。比如说,我点击了一个webelement,因此DOM中的其他一个元素发生了变化。现在,显然我会在这里得到一个StaleElementReferenceException
。我该如何解决这个问题?
我是否应该再次发现特定的WebElement知道DOM中的WebElement属性可能发生了变化?还是有另一种方法来处理这个问题?
StaleElementReferenceException扩展了WebDriverException并指示该元素的先前引用现在已过时且元素引用不再出现在页面的DOM上。
StaleElementReferenceException
背后的常见原因如下:
该元素已被完全删除。
该元素不再附加到DOM。
该元素所属的网页已刷新。
(previous)元素已被JavaScript或AjaxCall删除,并被具有相同ID
或其他属性的(new)元素替换。findElement()
或findElements
再次查找元素。initElements()
方法时,该页面的所有WebElements都将被初始化。例如,
LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class);
这行代码将初始化LoginPageNew.class
范围内定义的所有静态WebElements,无论何时何地从自动化脚本调用它。click()
标记上调用<input>
不会触发HTML DOM上任何WebElements的任何更改。
在click()
标签或<button>
标签上调用<a>
可以调用JavaScript或Ajax,其中可以删除元素或者可以用具有相同ID
或其他属性的(新)元素替换(previous)元素。因此,如果WebDriver抛出StaleElementReferenceException,这意味着即使元素仍然存在,引用也会丢失。我们应该丢弃当前的引用,并在它附加到DOM时再次找到WebElement来替换它。这意味着您必须通过initElements()
方法再次重新初始化该类,该方法将重新初始化该页面中定义的所有WebElements。
如果旧元素已被新的相同元素替换,则简单的策略是调用WebDriverWait与ExpectedConditions联合以查找元素。
您可以在以下位置找到相关的详细讨
以下是此讨论的参考:
这是PageFactory实现的一个已知问题。
如果你不幸的是元素在被找到的元素之间的瞬间变得陈旧,然后被点击的元素,你将得到这个错误。不幸的是,如果该元素变得陈旧并且它抛出异常,则它不会再尝试查找该元素。
我会把它归类为PageFactory的一个错误,它应该自动重新找到元素,如果它变得陈旧(除非使用@CacheLookup注释)。
调用initElements的建议不会解决任何问题,您只需要初始化元素一次,因为它将Java代理类绑定到相关元素。页面工厂实现应该删除StaleElementReferenceExceptions的可能性(因此这是一个错误)
Stale element exception
被抛出两个案例
该元素不再附加到DOM
。该元素已被完全删除。
当发生这种情况时,您将代码包装在try catch block
中,然后您可以根据需要循环并重试多次,直到成功为止。
public void waitForElementPresent(final By by, int timeout){
WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver,timeout)
.ignoring(StaleElementReferenceException.class);
wait.until(new ExpectedCondition<Boolean>(){
@Override
public Boolean apply(WebDriver webDriver) {
WebElement element = webDriver.findElement(by);
return element != null && element.isDisplayed();
}
});
}