有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Selenium fluentWait导致StaleElementReferenceException

我有一个场景,如下面的截图所示: 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毫秒后发生此超时?有什么办法可以让我满足这个要求吗

任何帮助都将不胜感激


共 (2) 个答案

  1. # 1 楼答案

    尽管页面上没有任何明显的变化,但在页面加载后,可能会有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;
    }
    
  2. # 2 楼答案

    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