有这样一种情况,我找到了内在的
div
,但由于StaleElementReferenceException
,取得了不同程度的成功。
<div role="dialog" aria-modal="true">
<div class="DialogBody"></div>
</div>
首先我找到
dialog
div,然后在找到内部 div时尝试避免
StaleElementReferenceException
WebElement dialog = null;
try {
dialog = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div[role='dialog']")));
} catch (TimeoutException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
logger.severe("no dialog banner after login");
}
logger.info("dialog found");
waitForChat(30);
try {
WebElement div = retryingFind(By.tagName("div"), dialog);
logger.info(div.getAttribute("class")); //null because the div is null
logger.info("inner div found");
} catch (TimeoutException e) {
ExceptionUtils.getStackTrace(e);
}
重试Find方法的地方:
public WebElement retryingFind(By by, WebElement el) {
WebElement result = null;
int attempts = 0;
while(attempts < 20) {
try {
result = el.findElement(by);
break;
} catch(StaleElementReferenceException e) {
System.out.println("StaleElementReferenceException");
}
attempts++;
}
return result;
}
有时内层div定位没有问题,但找到内层div时会随机出现StaleElementReferenceExceptions。这种情况如何解决?
据我了解,
StaleElementReferenceException
表示对元素的引用现在已过时,即该元素不再出现在页面的 HTML DOM 中,但该元素在检测到它时是可见的。
还建议检查 elementToBeClickable() 上的元素,但首先这对于 div 有意义吗,其次我通过另一个元素找到这个 div,而不是通过 webdriver,所以构造函数
new WebDriverWait(WebElement el, Duration)
未定义。
由于页面是动态的,某些因素导致
div role ='dialog'
发生变化,因此解决方案是更新此外部 div,如下所示:
public WebElement retryingFind(By by, WebElement el, WebDriverWait wait) {
WebElement result = null;
int attempts = 0;
while(attempts < 5) {
try {
result = el.findElement(by);
break;
} catch(StaleElementReferenceException e) {
try {
el = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div[role='dialog']")));
} catch (TimeoutException e1) {}
}
attempts++;
}
return result;
}
因此,我再也没有遇到过这个问题。