StaleElementReference异常的PageFactory(StaleElementRe

2019-09-30 01:58发布

我想学习PageFactory模型。 我明白了一个事实,当我们做一个initElements ,该WebElements所在。 比方说,我点击一个webelement因为其中有在DOM其他webelements的一个变化。 现在,很明显,我会得到一个StaleElementReferenceException这里。 我将如何解决这个问题?

我应该发现,特定WebElement再次知道的事实,有可能在DOM的WebElement的性质发生变化? 或者说还有什么别的办法来处理这个?

Answer 1:

StaleElementReferenceException

StaleElementReferenceException延伸WebDriverException并指示该元素的前一个参考已经陈旧和元素引用不再出现在页面的DOM。


常见原因

  • 面对背后的常见原因StaleElementReferenceException如下:
    • 该元素已经被全部删除。
    • 的元件不再连接到DOM。
    • 该网页上的元素是已被刷新的一部分。
    • 的(上次的)元件已经由JavaScript,或者AjaxCall的删除,并通过用相同的(新的)元素取代ID或其他属性。
  • 解决方法如果(旧)元素已被替换为新的相同的一个,简单的策略是使用findElement()findElements再次看出来的元素。

回答你的疑问

  1. 当我们做一个initElements,该WebElements位于 :当你调用initElements()方法,该页面的所有WebElements将得到初始化。 例如,

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

    这行代码将初始化的范围内定义的所有静态WebElements LoginPageNew.class无论何时何地它是从你的自动化脚本调用。

  2. 我点击一个webelement因为其中有在DOM其他webelements的一个变化 :这是非常可能的。

    • 作为一个例子,在一般调用click()上的<input>标签不会触发的任何对的WebElements的任何改变的HTML DOM
    • 其中作为调用click()上的<button>标签或<a>标签可以呼叫JavaScriptAjax的哪个inturn可以删除一个元素,或可通过一个(新)元件用相同的替换(先前)元素ID或其他属性。

结论

所以,如果webdriver的抛出一个StaleElementReferenceException,暗示即使元素依然存在,基准丢失。 我们应该抛弃目前的参考,我们必须通过再次定位WebElement当它被附加到DOM更换。 这意味着你必须再次重新初始化通过类initElements()方法,它inturn重新初始化在页面中定义的所有WebElements。


如果旧元素已被替换成新的一样一个,简单的策略是调用WebDriverWait inconjunction与ExpectedConditions看出来的元素。

你可以找到相关的详细讨论:

  • 如何添加明确的等待中PageFactory在PageObjectModel?

参考

以下是本次讨论的参考:

  • 过时的元素引用异常
  • 类StaleElementReferenceException
  • 硒:如何判断RemoteWebDriver.findElements(通过)可以抛出StaleElementReferenceException呢?


Answer 2:

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

如果你运气不好足够的元素之间的即时成为过时的元素被发现,然后元素被点击时,你会得到这个错误。 不幸的是,PageFactory代码不会尝试再次找到该元素,如果它已经成为陈旧,它抛出一个异常。

我想这个分类与PageFactory一个bug,它应该自动重新找到元素,如果它曾经变得陈旧(除非使用@CacheLookup注释)。

召回initElements的建议是不会解决任何事情,你只需要一次初始化的元素,因为结合Java代理类有问题的元素。 该网页工厂实现应该删除StaleElementReferenceExceptions的可能性(所以为什么这是一个bug)



Answer 3:

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(); 
    } 
  }); 
}


文章来源: StaleElementReference Exception in PageFactory