【问题标题】:Selenium StaleElementReferenceException while using EventFiringWebDriver使用 EventFiringWebDriver 时出现 Selenium StaleElementReferenceException
【发布时间】:2017-11-16 22:38:42
【问题描述】:

亲爱的,我正在使用 Selenium EventFiringWebDriver 来记录调用的 Web 驱动程序方法。我意识到我经常收到“StaleReferenceException”,而当我只使用 HtmlUnitDriver 时,我没有遇到问题。

我还认识到调用,即“click()”已经在浏览器中执行,尽管“StaleElementReferenceException”被抛出。

有没有人知道 EventFiringWebDriver 在使用 HtmlUnitDriver 或 FirefoxDriver 时遇到此类问题? 会不会是原始驱动程序在运行时更新了 WebElements 而 EventFiringWebDriver 的 wrapped WebElements 没有? 还是我们应该将此作为 EventFiringWebDriver 实现的错误提出?

带有 EventFiringWebDriver 的示例代码 - 抛出 StaleElementReferenceException

        HtmlUnitDriver driver = new HtmlUnitDriver();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

        ExtentReports extent = new ExtentReports ("report.html", true);
        ExtentTest logger = extent.startTest("test");

        EventFiringWebDriver eventDriver = new EventFiringWebDriver(driver);
        eventDriver.register(new MyWebDriverEventListener(logger));

        try {
            WebElement element  = null;
            eventDriver.get("https://www.google.com");
            element = eventDriver.findElement(By.xpath("//input[@type='text']"));
            element.sendKeys("Test");
            element.submit();
            Thread.sleep(2000);
            element = eventDriver.findElement(By.xpath("//div[@id='search']//a"));
            String title = element.getText();
            // HERE the StaleElementReferenceException get thrown ALTHOUGH the "click" event get processed by the browser, it loads already the page
            try {
                element.click();
            } catch(StaleElementReferenceException ex) {
            }
            Thread.sleep(2000);
            Assert.assertEquals(title, eventDriver.getTitle());
            logger.log(LogStatus.PASS,"end","Test passed");
         } catch(AssertionError error) {
            logger.log(LogStatus.FAIL,"end","Test failed:" + error.getMessage());
            throw error;
         }
        finally {
            extent.endTest(logger);
            extent.flush();
            extent.close();
            eventDriver.quit(); 
        }

相同的代码 - 直接使用 HtmlUnitDriver,没有任何问题

        HtmlUnitDriver driver = new HtmlUnitDriver();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

        ExtentReports extent = new ExtentReports ("report.html", true);
        ExtentTest logger = extent.startTest("test");

        try {
            WebElement element  = null;
            driver.get("https://www.google.com");
            element = driver.findElement(By.xpath("//input[@type='text']"));
            element.sendKeys("Test");
            element.submit();
            Thread.sleep(2000);
            element = driver.findElement(By.xpath("//div[@id='search']//a"));
            String title = element.getText();
            element.click();
            Thread.sleep(2000);
            Assert.assertEquals(title, driver.getTitle());
            logger.log(LogStatus.PASS,"end","Test passed");
         } catch(AssertionError error) {
            logger.log(LogStatus.FAIL,"end","Test failed:" + error.getMessage());
            throw error;
         }
        finally {
            extent.endTest(logger);
            extent.flush();
            extent.close();
            driver.quit(); 
        }

【问题讨论】:

    标签: java selenium selenium-webdriver htmlunit-driver stalestateexception


    【解决方案1】:

    在研究了陈旧异常的堆栈跟踪后,我意识到问题并非直接来自 EventFiringWebDriver。它被我的WebDriverEventListener 的侦听器实现抛出,而我在执行单击后尝试获取元素的标签名称。

    对我来说,WebDriverEventListener 的设计似乎不是最佳的。换句话说,您可能无法在“afterXXX”方法中使用传递的 WebElement,否则您可能会面临过时异常的风险。相反,您应该使用“beforeXXX”方法来检索元素的详细信息。

    我的 StaleElementReferenceException 的堆栈跟踪

    at org.openqa.selenium.htmlunit.HtmlUnitDriver.assertElementNotStale(HtmlUnitDriver.java:963)
    at org.openqa.selenium.htmlunit.HtmlUnitWebElement.assertElementNotStale(HtmlUnitWebElement.java:734)
    at org.openqa.selenium.htmlunit.HtmlUnitWebElement.getTagName(HtmlUnitWebElement.java:291)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.openqa.selenium.support.events.EventFiringWebDriver$EventFiringWebElement$1.invoke(EventFiringWebDriver.java:332)
    at com.sun.proxy.$Proxy18.getTagName(Unknown Source)
    at ch.megloff.test.SimpleExtentReportWebDriverEventListener.afterClickOn(SimpleExtentReportWebDriverEventListener.java:111)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.openqa.selenium.support.events.EventFiringWebDriver$1.invoke(EventFiringWebDriver.java:81)
    at com.sun.proxy.$Proxy16.afterClickOn(Unknown Source)
    at org.openqa.selenium.support.events.EventFiringWebDriver$EventFiringWebElement.click(EventFiringWebDriver.java:346)
    ..s
    

    底层HtmlUnit Implementation的“getTagName()”的Java代码sn-p

    public String getTagName() {
       assertElementNotStale();
       return element.getNodeName();
    } 
    

    我的这个“afterClickOn”方法的“容易出错”监听器实现 - 在执行点击后不应调用“getTagName()”

     public class MyWebDriverEventListener extends AbstractWebDriverEventListener {
        ...
        @Override
        public void afterClickOn(WebElement element, WebDriver driver) {
            // bad implementation, click has been already performed 
            // so you may risk to have a stale exception in case the 
            // browser  switched already to the other page (DOM got changed)
            logEvent("Clicked on tag: " + element.getTagName() + " with href: " + element.getAttribute("href"));
        }
     }
    

    【讨论】:

      猜你喜欢
      • 2014-03-03
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-19
      相关资源
      最近更新 更多