Java 使用EventFiringWebDriver时出现Selenium StaleElementReferenceException异常
亲爱的各位,我正在使用SeleniumEventFiringWebDriver记录被调用的web驱动程序方法。我意识到,当我单独使用HtmlUnitDriver时,我经常会得到一个“”而我没有这个问题 我还认识到,虽然抛出了“StaleElementReferenceException”,但调用“click()”已在浏览器中执行 当EventFiringWebDriver在使用HtmlUnitDriver或FirefoxDriver时遇到这样的问题时,有人想到了吗? 可能是源驱动程序在运行时更新了WebElements,而EventFiringWebDriver的源驱动程序没有更新吗? 或者我们应该将其作为EventFiringWebDriver实现的一个bug提出 EventFiringWebDriver示例代码-抛出StaleElementReferenceExceptionJava 使用EventFiringWebDriver时出现Selenium StaleElementReferenceException异常,java,selenium,selenium-webdriver,htmlunit-driver,stalestateexception,Java,Selenium,Selenium Webdriver,Htmlunit Driver,Stalestateexception,亲爱的各位,我正在使用SeleniumEventFiringWebDriver记录被调用的web驱动程序方法。我意识到,当我单独使用HtmlUnitDriver时,我经常会得到一个“”而我没有这个问题 我还认识到,虽然抛出了“StaleElementReferenceException”,但调用“click()”已在浏览器中执行 当EventFiringWebDriver在使用HtmlUnitDriver或FirefoxDriver时遇到这样的问题时,有人想到了吗? 可能是源驱动程序在运行时更新
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();
}
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
同样的代码——只需直接使用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();
}
在研究过时异常的堆栈跟踪后,我发现问题并非直接来自EventFiringWebDriver。当我在执行单击后尝试获取元素的标记名时,它由的侦听器实现抛出 对我来说,它的设计似乎不是最优的。换言之,您可能无法在“afterXXX”方法中使用传递的WebElement,否则您可能会面临过时异常的风险。相反,您应该使用“beforeXXX”方法来检索元素的详细信息 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();
}
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代码片段
此“afterClickOn”方法的“易出错”侦听器实现-执行单击后不应调用“GetTaName()”
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"));
}
}