【问题标题】:Selenium fluentWait is resulting in a StaleElementReferenceExceptionSelenium fluentWait 导致 StaleElementReferenceException
【发布时间】:2015-02-17 06:17:12
【问题描述】:

我有一个场景,如下面的屏幕截图所示:

所以,我构建了一些代码,可以让我单击左侧的条形图....每次我这样做都会在右侧显示一个关系条形图。如果左侧的条形图特别大,右侧的关系条形图可能需要一段时间才能显示出来。为了解决这个问题,我构建了一个 fluentWait 方法,如下所示:

    public static void fluentWaitOnRelationalBarChartSelector(InternetExplorerDriver driver)
    {
        WebElement relationalBarSelect = (new WebDriverWait(driver, 20))
                .until(ExpectedConditions.elementToBeClickable(By.tagName("rect")));
        relationalBarSelect.click();
    }

但是,并非总是如此,但有时,我会在控制台中收到如下错误:

Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: Element is no longer valid
(WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 33 milliseconds

我不确定为什么在我应用 20 秒等待后 33 毫秒后会发生此超时?有没有办法让我满足这个StaleElementReferenceException

任何帮助将不胜感激。

【问题讨论】:

  • 只是一个更正@Andy。 FluentWait 是 selenium java 绑定的一个类,机制与 WebDriverWait 不同,FluentWait 的子类。见this
  • 感谢您的提示,赛夫 :-)
  • 不客气。让我知道解决方案是否有效。

标签: java eclipse selenium webdriver


【解决方案1】:

StaleElementReferenceException 是一个非常痛苦且非常具体的元素。这通常意味着该元素无法与 selenium 交互,因为您的设置存在很多问题。为了解决这个问题,人们使用了两种不同的机制(至少据我所知)。 FluentWait 可能会救你一命。类似于以下内容:

// Waiting 30 seconds for an element to be present on the page, checking
   // for its presence once every 5 seconds.
   Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
       .withTimeout(30, SECONDS)
       .pollingEvery(5, SECONDS)
       .ignoring(NoSuchElementException.class);

   WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
     public WebElement apply(WebDriver driver) {
       return driver.findElement(By.id("foo"));
     }
   });

取自here。值得一提的是,它还允许您等待一个元素而忽略其他一些异常。

如果这不起作用,则估计可能足以使该元素准备好进行交互的循环数。不是我最喜欢的,但很有效。

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

取自here

【讨论】:

  • 太棒了,赛弗,谢谢。效果很好!
【解决方案2】:

即使页面上没有明显的变化,在页面加载后,可能还有 JavaScript 会改变 WebElement 的属性。此 JavaScript 可能由您的脚本执行的先前操作触发(例如:单击其他一些 WebElement)。

如果您在 WebElement 的属性更改后尝试与它进行交互(单击、发送键等),selenium 将抛出 StaleElementReferenceException。在这种情况下,您的代码应该多次重试该操作,而不是在第一次尝试时抛出异常,见下文。

public static Boolean executeElementClick
  (WebDriver driver, WebElement element, int MaxTimeToWait) throws Exception {
    // Local variable declaration
    String sElementString = "";
    String sElementXpath = "";
    Boolean returnValue = false;
    int index = 0;

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

    // Keep trying until 'MaxTimeToWait' is reached 
    for (int loop = 0; loop < MaxTimeToWait; loop++) {
        try {
            // Get element xPath - and find element again
            if (element != null && loop < 1 && sElementXpath.equals("")) {
                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.equals("") && loop > 0) {
                element = driver.findElement(By.xpath(sElementXpath));
            }

            // Execute the action requested
            element.click();
            returnValue = true;

        } catch (Exception e) {
            Thread.sleep(1000);
            returnValue = false;
        }

        if (returnValue) {
            System.out.println("**** PASSED: Clicked on '" + sElementString + "'");
            break;
        }
    }
    // Reset browser timeout to default
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

    return returnValue;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 2014-11-15
    相关资源
    最近更新 更多