PageFactory中的StaleElementReference异常

问题描述 投票:1回答:1

我正在尝试学习PageFactory模型。我了解一个事实,当我们执行initElements时,将定位WebElement。举例来说,我单击一个Web元素,因此DOM中的其他Web元素之一发生了变化。现在,显然我会在这里得到一个StaleElementReferenceException。我该如何解决这个问题?

我应该再次知道特定的WebElement知道DOM中WebElement的属性可以更改的事实吗?还是有另一种方法来处理此问题?

r selenium rselenium
1个回答
13
投票

StaleElementReferenceException

[StaleElementReferenceException扩展WebDriverException,并指示元素的先前引用现在为stale,并且元素引用不再存在于页面的DOM上。


常见原因

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

回答您的查询

  1. [当我们执行initElements时,WebElements位于]:当您调用initElements()方法时,该页面的所有WebElements将被初始化。例如,

    LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class);
    

    此代码行将随时随地从自动化脚本中调用LoginPageNew.class范围内定义的所有静态WebElements初始化。

  2. 我单击一个Web元素,因此DOM中其他Web元素之一发生了变化:这几乎是可能的。

    • 例如,通常在click()标签上调用<input>不会触发HTML DOM上任何WebElements的任何更改。
    • click()标记或<button>标记上调用<a>的地方可能调用JavaScriptAjax,这反过来可能会删除一个元素或可以用( (新)具有相同ID或其他属性的元素。

结论

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


解决方案

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

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


参考

这里是此讨论的参考:


2
投票

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

如果不幸的是,在找到的元素与被单击的元素之间的瞬间,该元素变得过时,则会出现此错误。不幸的是,如果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.