Selenium WebDriver StaleElementReferenceException

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Selenium WebDriver StaleElementReferenceException相关的知识,希望对你有一定的参考价值。

运行我的测试时出现此错误:org.openqa.selenium.StaleElementReferenceException:元素不再附加到DOM

关于如何解决上述异常的任何想法?这发生在我的网格中,它有一个动态的ref Xpath表达式

答案

我遇到了同样的问题,找不到任何解决方案。想出一个解决方案并将其发布在这里,希望这可以帮助有同样问题的人。我创建了一个类来处理陈旧元素,具体取决于它们的类型,cssselector,id等,并简单地调用它,就像我任何其他页面对象一样。

public void StaleElementHandleByID (String elementID){
int count = 0;
boolean clicked = false;
while (count < 4 || !clicked){
    try {
       WebElement yourSlipperyElement= driver.findElement(By.id(elementID));
       yourSlipperyElement.click(); 
       clicked = true;
     } catch (StaleElementReferenceException e){
       e.toString();
       System.out.println("Trying to recover from a stale element :" + e.getMessage());
       count = count+1;
     }     
}

我建议只在你知道导致WebDriver出现问题的元素上使用它。

另一答案

快速而肮脏的解决方案:

el.click()

time.sleep(1)

然后继续以迭代方式解析

另一答案

我们通过做一些名为WebdriverWrapper和WebElementWrapper的事来解决这个问题。

这些包装器所做的是处理其中的StaleElementException,然后使用定位器重新计算并获取新的WebElement对象。这样,您需要在代码库中传播处理异常的代码,并将其本地化为一个类。

我将很快调查这几个类的开源,如果你有兴趣,我会在这里添加一个链接。

另一答案

当您尝试使用页面上不再存在的WebElement方法时,将引发该异常。如果您的网格是动态加载数据并刷新网格,那么对该网格上元素的任何引用都将是“陈旧的”。仔细检查您尝试引用的元素是否在测试的页面上,您可能需要重新实例化该对象。

另一答案

它也遇到了这个问题,看起来很明显模态面板加载处于竞争状态并且一直等到超时。

我已经尝试了很多次,并且发现解决方案是保持模态面板加载,直到webDriver可以找到它并同时保持刷新webDriver实例,然后尝试在模态面板中找到WebElements。

所以解决方案如下:例如MyModalPanel是您的ModalPanel ID,然后执行以下操作

page.openModalPanel();
Assert.assertTrue(page.waitTillDisplay( "MyModalPanelContentDiv"), Wait.MODAL_PANEL));
page.fillInFormInModalpanel(formObj);

并且可以在WebDriver网站上找到waitTillDisplay代码,我将在此处粘贴我的代码供您参考:

public Boolean waitTillDisplay(final String id, int waitSeconds){

    WebDriverWait wait = new WebDriverWait(driver, waitSeconds);
        Boolean displayed = wait.until(new ExpectedCondition<Boolean>() {
              public Boolean apply(WebDriver driver) {
                  return driver.findElement(By.id(id)).isDisplayed();
              }

        });
        return displayed;

}

另一答案

单击元素后,您可能尝试获取任何元素属性。

我遇到了同样的问题,我点击了按钮后尝试getText()。在我的情况下,一旦点击按钮,就会出现新窗口。

另一答案

我使用了FluentWait和ExpectedCondition应用覆盖:https://gist.github.com/djangofan/5112655。这个处理最终块内的异常,不像其他人回答这个问题,并允许连续的尝试包含在该块中。我觉得这更优雅。

public static void clickByLocator( final By locator ) {
  final long startTime = System.currentTimeMillis();
  driver.manage().timeouts().implicitlyWait( 5, TimeUnit.SECONDS );
  Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
        .withTimeout(90000, TimeUnit.MILLISECONDS)
        .pollingEvery(5500, TimeUnit.MILLISECONDS);
        //.ignoring( StaleElementReferenceException.class );        
  wait.until( new ExpectedCondition<Boolean>() { 
    @Override 
    public Boolean apply( WebDriver webDriver ) {
      try {
        webDriver.findElement( locator ).click();
        return true;
      } catch ( StaleElementReferenceException e ) {                      // try again
        return false;
      }     
    } 
  } );      
  driver.manage().timeouts().implicitlyWait( DEFAULT_IMPLICIT_WAIT, TimeUnit.SECONDS );
  long endTime   = System.currentTimeMillis();
  long totalTime = endTime - startTime;
  log("Finished click after waiting for " + totalTime + " milliseconds.");
}
另一答案
public static Boolean executeElementSendKeys
(WebDriver driver, WebElement element, String sInputParameters) throws Exception {
    return (Boolean) executeElementMaster
            (driver, element, "sendKeys", sInputParameters, 30, true);
}

public static Boolean executeElementClear
(WebDriver driver, WebElement element) throws Exception {
    return (Boolean) executeElementMaster (driver, element, "clear", "", 30, true);
}

public static String executeElementGetText
(WebDriver driver, WebElement element) throws Exception {
    return (String) executeElementMaster (driver, element, "getText", "", 30, true);
}

public static Boolean executeElementClick
(WebDriver driver, WebElement element) throws Exception {
    return (Boolean) executeElementMaster (driver, element, "click", "", 30, true);
}

public static boolean executeElementIsDisplayed
(WebDriver driver, WebElement element) throws Exception {
    return (Boolean) executeElementMaster (driver, element, "isDisplayed", "", 30, true);
}

public static String executeElementGetAttribute
(WebDriver driver, WebElement element, String sInputParameters) throws Exception {
    return (String) executeElementMaster
            (driver, element, "getAttribute", sInputParameters, 30, true);
}

//以下是处理StaleElementReferenceException和其他异常的主方法。

//在catch部分中,如果您希望此方法仅针对(Exception e)而不是其他异常重试操作(如click,sendkeys等),请将(StaleElementReferenceException e)替换为StaleElementReferenceException

private static Object executeElementMaster(WebDriver driver, WebElement element, String sExecuteAction, String sInputParametersOptional, int MaxTimeToWait,
        boolean bExpectedElementState) throws Exception {
    try {
        // Local variable declaration
        String sElementString = "";
        String sElementXpath = "";
        Object ReturnValue = "";
        int Index = 0;
        boolean bCurrentElementState = true;
        boolean bWebDriverWaitUntilElementClickableFlag = false;

        System.out.println("**** Execute method '" + sExecuteAction + "' on '" + sElementString + "' - Expected : '" + bExpectedElementState + "'");
        System.out.println("**** MaxTimeToWait ='" + MaxTimeToWait + "' seconds");

        // Set browser timeout to 1 second. Will be reset to default later
        driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);

        // Keep trying until 'MaxTimeToWait' is reached 
        for (int i = 0; i < MaxTimeToWait; i++) {
            try {
                // Get element xPath - and find element again
                if (element != null && i < 2 && sElementString == "") {
                    sElementString = (element).toString();
                    if (sElementString.contains("xpath: ")) {
                        // Retrieve xPath from element, if available
                        Index = sElementString.indexOf("xpath: ");
                        sElementXpath = sElementString.substring(Index + 7, sElementString.length());
                    }
                }

                // Find Element again
                if (sElementXpath != "" && i > 0) {
                    element = driver.findElement(By.xpath(sElementXpath));
                }

                // Execute the action requested
                switch (sExecuteAction) {
                    case ("isDisplayed"):
                        // Check if element is displayed and save in bCurrentElementState variable
                        ReturnValue = element.isDisplayed();
                        bCurrentElementState = (Boolean) ReturnValue;
                        bWebDriverWaitUntilElementClickableFlag = true;
                        break;
                    case ("getText"):
                        ReturnValue = element.getText();
                        bCurrentElementState = true;
                        bWebDriverWaitUntilElementClickableFlag = false;
                        break;
                    case ("sendKeys"):
                        // Scroll element into view before performing any action

                        element.sendKeys(sInputParametersOptional);
                        ReturnValue = true;
                        bCurrentElementState = true;
                        bWebDriverWaitUntilE

以上是关于Selenium WebDriver StaleElementReferenceException的主要内容,如果未能解决你的问题,请参考以下文章

Selenium Webdriver概述

appium的webdriver和selenium有啥区别?

selenium之python源码解读-webdriver继承关系

From  selenium  import  webdriver

Selenium WebDriver(Python)API

selenium+python - webdriver​模拟键盘ENTER没有效果