我有一个场景,如下面的屏幕截图所示:
所以,我已经构建了一些代码,允许我点击左侧的条形图....每次我这样做都会在右边显示一个关系条形图。如果条形图在左侧特别大,则右侧的关系条形图可能需要一段时间才能显示。为了解决这个问题,我构建了一个fluentWait方法,如下所示:
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
?
任何帮助都将不胜感激。
答案 0 :(得分:1)
StaleElementReferenceException
是一个非常痛苦且非常具体的元素。它通常意味着元素无法与硒交互,因为很多问题都与您的设置非常相关。要解决这个问题,人们会使用两种不同的机制(至少根据我的知识)。 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"));
}
});
取自here。值得一提的是,它允许您等待一个元素忽略其他一些例外。
如果这不起作用,那么估计一个可能足以使该元素准备好进行交互的循环。不是我的最爱,但有效。
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;
}
取自here
答案 1 :(得分:0)
即使页面上没有任何内容发生明显变化,但在页面加载后,可能还有其他一些JavaScript会更改WebElement
的属性。此脚本可能由您的脚本执行的先前操作触发(例如:点击其他WebElement
)。
如果您尝试在WebElement的属性发生变化后与WebElement进行交互(click,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;
}