Selenium fluentWait导致StaleElementReferenceException

时间:2014-12-18 12:46:27

标签: java eclipse selenium webdriver

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

所以,我已经构建了一些代码,允许我点击左侧的条形图....每次我这样做都会在右边显示一个关系条形图。如果条形图在左侧特别大,则右侧的关系条形图可能需要一段时间才能显示。为了解决这个问题,我构建了一个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

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:1)

StaleElementReferenceException是一个非常痛苦且非常具体的元素。它通常意味着元素无法与硒交互,因为很多问题都与您的设置非常相关。要解决这个问题,人们会使用两种不同的机制(至少根据我的知识)。 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

答案 1 :(得分:0)

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

如果您尝试在WebElement的属性发生变化后与WebElement进行交互(click,sendkeys等...),则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;
}