亲爱的所有我使用Selenium EventFiringWebDriver来记录被调用的Web驱动程序方法。我认识到我经常得到一个" StaleReferenceException"而当我只使用HtmlUnitDriver时,我没有问题。
我也认出了这个电话,即" click()"已经在浏览器中执行了#34; StaleElementReferenceException"被扔了。
当使用HtmlUnitDriver或FirefoxDriver独立时,EventFiringWebDriver遇到此类问题时是否有任何想法? 可能是在运行时由原始驱动程序更新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 :(得分:0)
在研究过时异常的堆栈跟踪后,我发现问题不是直接来自EventFiringWebDriver。当我尝试在执行单击后获取元素的标记名称时,它会被WebDriverEventListener的侦听器实现抛出。
对我来说,WebDriverEventListener的设计看起来不是最佳的。换句话说,您可能无法在" afterXXX"中使用传递的WebElement。方法,否则你可能会冒失败的例外。相反,你应该使用" beforeXXX"方法,以检索元素的细节。
我的StaleElementReferenceException的Stacktrace
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
" getTagName()"的Java代码片段基础HtmlUnit Implementation
public String getTagName() {
assertElementNotStale();
return element.getNodeName();
}
My"容易出错"这个" 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"));
}
}