0

亲爱的我所有使用Selenium EventFiringWebDriver记录被调用的Web驱动程序方法。我意识到我经常得到一个“StaleReferenceException”,而当我单独使用HtmlUnitDriver时,我没有问题。使用EventFiringWebDriver时Selenium StaleElementReferenceException

我也认识到虽然抛出了“StaleElementReferenceException”,但是在浏览器中执行了“click()”这个调用。

有没有人有一个想法,而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(); 
     } 

回答

0

学习陈旧的例外,我认识的堆栈跟踪后该问题不直接来自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 

Java代码片断 “getTagName()” 的基本HtmlUnit Implementation

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")); 
    } 
} 
相关问题