PageFactory中的StaleElementReference异常

问题描述 投票:8回答:3

我正在尝试学习PageFactory模型。我理解当我们做initElements时,WebElements就位于。比如说,我点击了一个webelement,因此DOM中的其他一个元素发生了变化。现在,显然我会在这里得到一个StaleElementReferenceException。我该如何解决这个问题?

我是否应该再次发现特定的WebElement知道DOM中的WebElement属性可能发生了变化?还是有另一种方法来处理这个问题?

selenium selenium-webdriver pageobjects page-factory staleelementreferenceexception
3个回答
12
投票

Sthalilementrepherensaessptivn

StaleElementReferenceException扩展了WebDriverException并指示该元素的先前引用现在已过时且元素引用不再出现在页面的DOM上。


常见原因

  • 面对StaleElementReferenceException背后的常见原因如下: 该元素已被完全删除。 该元素不再附加到DOM。 该元素所属的网页已刷新。 (previous)元素已被JavaScript或AjaxCall删除,并被具有相同ID或其他属性的(new)元素替换。
  • 解决方案:如果(旧)元素已替换为新的相同元素,则简单的策略是使用findElement()findElements再次查找元素。

回答你的疑问

  1. 当我们执行initElements时,WebElements位于:当您调用initElements()方法时,该页面的所有WebElements都将被初始化。例如, LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class); 这行代码将初始化LoginPageNew.class范围内定义的所有静态WebElements,无论何时何地从自动化脚本调用它。
  2. 我点击了一个webelement,因此DOM中的其他一个元素发生了变化:这几乎是可能的。 例如,通常在click()标记上调用<input>不会触发HTML DOM上任何WebElements的任何更改。 在click()标签或<button>标签上调用<a>可以调用JavaScript或Ajax,其中可以删除元素或者可以用具有相同ID或其他属性的(新)元素替换(previous)元素。

结论

因此,如果WebDriver抛出StaleElementReferenceException,这意味着即使元素仍然存在,引用也会丢失。我们应该丢弃当前的引用,并在它附加到DOM时再次找到WebElement来替换它。这意味着您必须通过initElements()方法再次重新初始化该类,该方法将重新初始化该页面中定义的所有WebElements。


如果旧元素已被新的相同元素替换,则简单的策略是调用WebDriverWaitExpectedConditions联合以查找元素。

您可以在以下位置找到相关的详细讨


参考

以下是此讨论的参考:


2
投票

这是PageFactory实现的一个已知问题。

如果你不幸的是元素在被找到的元素之间的瞬间变得陈旧,然后被点击的元素,你将得到这个错误。不幸的是,如果该元素变得陈旧并且它抛出异常,则它不会再尝试查找该元素。

我会把它归类为PageFactory的一个错误,它应该自动重新找到元素,如果它变得陈旧(除非使用@CacheLookup注释)。

调用initElements的建议不会解决任何问题,您只需要初始化元素一次,因为它将Java代理类绑定到相关元素。页面工厂实现应该删除StaleElementReferenceExceptions的可能性(因此这是一个错误)


1
投票

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(); 
    } 
  }); 
}
© www.soinside.com 2019 - 2024. All rights reserved.