Java StaleElementReferenceException,即使使用'FluentWait<&燃气轮机`
我在ubto上运行webe2e测试(使用cucumber、junit、seleniumwebdriver) 使用remoteWebDriver时,我的测试偶尔会失败(使用本地webDriver时从不失败) 当我将代码重构为以下内容时,我认为我绕过了此异常:Java StaleElementReferenceException,即使使用'FluentWait<&燃气轮机`,java,google-chrome,selenium,selenium-webdriver,webdriver,Java,Google Chrome,Selenium,Selenium Webdriver,Webdriver,我在ubto上运行webe2e测试(使用cucumber、junit、seleniumwebdriver) 使用remoteWebDriver时,我的测试偶尔会失败(使用本地webDriver时从不失败) 当我将代码重构为以下内容时,我认为我绕过了此异常: public String getSrcAfterWait(final By by) { WebElement webElement = getElementAfterWaitForDisplay2(by);
public String getSrcAfterWait(final By by) {
WebElement webElement = getElementAfterWaitForDisplay2(by);
String currentSrc = null;
if (webElement != null) {
currentSrc = webElement.getAttribute("src");
}
return currentSrc;
}
public WebElement getElementAfterWaitForDisplay2(final By by) {
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class, StaleElementReferenceException.class);
return wait.until(ExpectedConditions.presenceOfElementLocated(by));
}
如果页面是动态的,则可能发生以下情况 情景1。 在方法“getSrcAfterWait”中,您找到了带有“getElementAfterWaitForDisplay2”的元素。但是在调用webElement.getAttribute(“src”)之前,页面上的元素会发生变化。当您调用webElement.getAttribute(“src”)时,“webElement”指向一个已经过时(不再存在)的元素。这将导致StaleElementReferenceException 情景2。 也许你有一些动画。这样就可以周期性地多次创建元素的新实例。“getElementAfterWaitForDisplay2”总是为“By”条件查找元素,但有时它是页面上较新的对象。找到元素后,在调用webElement.getAttribute(“src”)之前,在页面上(在DOM中)创建了一个新实例。因此,您定位的变量引用已经过时的实例 两种情况下的简单解决方案是:捕获异常并再次定位对象
更复杂但更通用的解决方案:使用代理对象并在那里实现异常处理和定位。@EladBenda:不太可能。你应该在一个循环中完成。但是您不需要编写循环代码。改用FluentWait。您只需将方法“getButtonTextAfterWait”转换为ExpectedCondition、谓词或函数,然后将其传递给FluentWait。您不需要显式捕获异常。您可以通过忽略(…Exception.class)来实现这一点,就像您在另一个地方所做的那样。它可以如下所示:
Wait wait = new FluentWait(driver)
.withTimeout(60, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class, StaleElementReferenceException.class);
String text = wait.until(new Function() {
public String apply(WebDriver driver) {
WebElement element = driver.findElement(By.id("..."));
return element.getText(); // or webElement.getAttribute("src") etc.
}
});
(1) 在
getElementAfterWaitForDisplay2
中请求src
是否也能解决问题?(2) 捕获异常并再次定位对象
-建议我在catch块中再次调用getsrcapterwait
?或者这里不推荐递归?嗯。您是否可以提供有关使用代理对象的更多详细信息?顺便说一句,可能是更接近的答案
public String getButtonTextAfterWait(final By by) {
String currentText;
try {
currentText = tryToGetText(by);
} catch (StaleElementReferenceException ex)
{
currentText = tryToGetText(by);
}
return currentText;
}
Wait wait = new FluentWait(driver)
.withTimeout(60, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class, StaleElementReferenceException.class);
String text = wait.until(new Function() {
public String apply(WebDriver driver) {
WebElement element = driver.findElement(By.id("..."));
return element.getText(); // or webElement.getAttribute("src") etc.
}
});
public void waitForElementBeDisplay(WebElement element) {
Wait wait = new FluentWait(driver).withTimeout(Duration.ofSeconds(30)).ignoring(StaleElementReferenceException.class).pollingEvery(Duration.ofSeconds(2));
wait.until(ExpectedConditions.refreshed(ExpectedConditions.visibilityOf(element)));
}