Java Selenium fluentWait导致StaleElementReferenceException
我有一个场景,如下面的截图所示: 所以,我已经构建了一些代码,可以让我点击左边的条形图……每次我点击,它都会在右边显示一个关系条形图。如果左侧的条形图特别大,则右侧的关系条形图可能需要一段时间才能显示出来。为了解决这个问题,我构建了一个fluentWait方法,如下所示:Java Selenium fluentWait导致StaleElementReferenceException,java,eclipse,selenium,webdriver,Java,Eclipse,Selenium,Webdriver,我有一个场景,如下面的截图所示: 所以,我已经构建了一些代码,可以让我点击左边的条形图……每次我点击,它都会在右边显示一个关系条形图。如果左侧的条形图特别大,则右侧的关系条形图可能需要一段时间才能显示出来。为了解决这个问题,我构建了一个fluentWait方法,如下所示: public static void fluentWaitOnRelationalBarChartSelector(InternetExplorerDriver driver) { WebEl
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
但是,不总是,但有时,我在控制台中遇到如下错误:
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毫秒后发生此超时?有没有一种方法可以满足这个StaleElementReferenceException
任何帮助都将不胜感激。
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"));
}
});
//等待30秒,让元素出现在页面上,检查
//每5秒检查一次。
等待等待=新建FluentWait(驱动程序)
.带超时(30秒)
.每(5秒)轮询一次
.忽略(NoSuchElementException.class);
WebElement foo=wait.until(新函数(){
公共WebElement应用(WebDriver){
返回驱动程序findElement(By.id(“foo”);
}
});
摘自。值得一提的是,它允许您等待一个元素,同时忽略其他一些异常
如果这不起作用,那么估计一个循环的数量,这可能足以让该元素准备好进行交互。不是我最喜欢的,但很管用
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;
}
public void StaleElementHandleByID(字符串elementID){
整数计数=0;
而(计数<4){
试一试{
WebElement yourSlipperyElement=driver.findElement(By.id(elementID));
您的SlipperyElement.click();
}捕获(StaleElementReferenceException e){
e、 toString();
System.out.println(“试图从过时元素中恢复:+e.getMessage());
计数=计数+1;
}
计数=计数+4;
}
摘自即使页面上没有任何明显的变化,页面加载后可能会有JavaScript等更改
Web元素
属性的内容。此JavaScript可能由脚本执行的前一个操作触发(例如:单击其他Web元素
)
如果在WebElement的属性更改后尝试与WebElement交互(单击、sendkeys等),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;
}
publicstaticbooleaneexecuteelementclick
(WebDriver驱动程序、WebElement元素、int MaxTimeToWait)引发异常{
//局部变量声明
字符串sElementString=“”;
字符串sElementXpath=“”;
布尔返回值=false;
int指数=0;
//将浏览器超时设置为1秒。稍后将重置为默认值
driver.manage().timeouts().implicitlyWait(0,TimeUnit.SECONDS);
//继续尝试,直到达到“MaxTimeToWait”
for(int-loop=0;loop0){
element=driver.findElement(By.xpath(sElementXpath));
}
//执行请求的操作
元素。单击();
returnValue=true;
}捕获(例外e){
睡眠(1000);
returnValue=false;
}
如果(返回值){
System.out.println(“****已通过:单击“+sElementString+””);
打破
}
}
//将浏览器超时重置为默认值
driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);
返回值;
}
只是一个更正@Andy。FluentWait
是一类selenium java绑定,其机制与WebDriverWait
不同,后者是FluentWait
的一个子类。请参阅感谢提示,Saifur:-)不客气。尽管如此,请告诉我该解决方案是否有效。太棒了,Saifur,谢谢。它工作得很出色真的!