我正在尝试学习 PageFactory 模型。我明白当我们做 a 时initElements
,WebElements 就被定位了。例如,我单击一个 web 元素,因此 DOM 中的其他 web 元素之一发生了变化。现在,显然我会在StaleElementReferenceException
这里得到一个。我将如何解决这个问题?
我是否应该再次找到特定的 WebElement,知道 WebElement 在 DOM 中的属性可能会发生变化?还是有另一种方法来处理这个?
我正在尝试学习 PageFactory 模型。我明白当我们做 a 时initElements
,WebElements 就被定位了。例如,我单击一个 web 元素,因此 DOM 中的其他 web 元素之一发生了变化。现在,显然我会在StaleElementReferenceException
这里得到一个。我将如何解决这个问题?
我是否应该再次找到特定的 WebElement,知道 WebElement 在 DOM 中的属性可能会发生变化?还是有另一种方法来处理这个?
StaleElementReferenceException扩展了WebDriverException并指示元素的先前引用现在已过时并且元素引用不再存在于页面的 DOM 上。
StaleElementReferenceException
如下:
ID
或其他属性的(新)元素替换。findElement()
或findElements
寻找该元素。当我们执行 initElements 时,WebElements 位于:当您调用initElements()
方法时,该页面的所有WebElements都将被初始化。例如,
LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class);
这行代码将初始化在您的自动化脚本中无论何时何地调用它的范围内定义的所有静态WebElement 。LoginPageNew.class
我单击一个 web 元素,因此 DOM 中的其他 web 元素之一发生了变化:这很有可能。
click()
在<input>
标签上调用不会触发HTML DOM上任何WebElement的任何更改。click()
上调用可能会调用JavaScript或Ajax ,这反过来可能会删除元素或可以用具有相同或其他属性的(新)元素替换(先前)元素。<button>
<a>
ID
因此,如果WebDriver抛出StaleElementReferenceException,这意味着即使元素仍然存在,引用也会丢失。我们应该丢弃我们拥有的当前引用,并通过在WebElement附加到 DOM 时再次定位它来替换它。这意味着您必须再次通过方法重新初始化该类,该方法又重新初始化该页面中定义的initElements()
所有WebElement 。
如果旧元素已被新的相同元素替换,简单的策略是调用WebDriverWait与ExpectedConditions结合以查找该元素。
您可以在以下位置找到相关的详细讨论:
以下是本次讨论的参考资料:
这是 PageFactory 实现的一个已知问题。
如果您很不幸,在找到元素和单击该元素之间的瞬间元素变得陈旧,您将收到此错误。不幸的是,如果 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();
}
});
}