hoa*_*yen 67 java selenium-webdriver
我正在使用Java实现许多Selenium测试.有时,我的测试由于a而失败StaleElementReferenceException.你能建议一些让测试更稳定的方法吗?
jsp*_*cal 68
如果页面上发生的DOM操作暂时导致元素不可访问,则会发生这种情况.为了允许这些情况,您可以在最终抛出异常之前尝试在循环中多次访问该元素.
从darrelgrainger.blogspot.com尝试这个出色的解决方案:
public boolean retryingFindClick(By by) {
boolean result = false;
int attempts = 0;
while(attempts < 2) {
try {
driver.findElement(by).click();
result = true;
break;
} catch(StaleElementException e) {
}
attempts++;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
Ken*_*nny 61
我间歇性地遇到这个问题.我不知道,BackboneJS正在页面上运行并替换我试图点击的元素.我的代码看起来像这样.
driver.findElement(By.id("checkoutLink")).click();
Run Code Online (Sandbox Code Playgroud)
这当然在功能上与此相同.
WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
checkoutLink.click();
Run Code Online (Sandbox Code Playgroud)
偶尔会发生的是javascript将在查找和单击它之间替换checkoutLink元素,即.
WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
// javascript replaces checkoutLink
checkoutLink.click();
Run Code Online (Sandbox Code Playgroud)
在尝试单击链接时,这正确地导致了StaleElementReferenceException.我找不到任何可靠的方法告诉WebDriver等到javascript运行完毕,所以这就是我最终如何解决它.
new WebDriverWait(driver, timeout)
.ignoring(StaleElementReferenceException.class)
.until(new Predicate<WebDriver>() {
@Override
public boolean apply(@Nullable WebDriver driver) {
driver.findElement(By.id("checkoutLink")).click();
return true;
}
});
Run Code Online (Sandbox Code Playgroud)
此代码将不断尝试单击该链接,忽略StaleElementReferenceExceptions,直到单击成功或达到超时.我喜欢这个解决方案,因为它可以节省您编写任何重试逻辑,并且只使用WebDriver的内置结构.
Jim*_*mes 15
通常这是由于DOM正在更新并且您尝试访问更新的/新元素 - 但DOM已刷新,因此它是您的无效引用.
首先使用元素上的显式等待来确保更新完成,然后再次获取对元素的新引用.
这里有一些伪代码来说明(改编自我使用的一些C#代码这个问题):
WebDriverWait wait = new WebDriverWait(browser, TimeSpan.FromSeconds(10));
IWebElement aRow = browser.FindElement(By.XPath(SOME XPATH HERE);
IWebElement editLink = aRow.FindElement(By.LinkText("Edit"));
//this Click causes an AJAX call
editLink.Click();
//must first wait for the call to complete
wait.Until(ExpectedConditions.ElementExists(By.XPath(SOME XPATH HERE));
//you've lost the reference to the row; you must grab it again.
aRow = browser.FindElement(By.XPath(SOME XPATH HERE);
//now proceed with asserts or other actions.
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
coc*_*llo 11
肯尼的解决方案很好,但它可以用更优雅的方式编写
new WebDriverWait(driver, timeout)
.ignoring(StaleElementReferenceException.class)
.until((WebDriver d) -> {
d.findElement(By.id("checkoutLink")).click();
return true;
});
Run Code Online (Sandbox Code Playgroud)
或者:
new WebDriverWait(driver, timeout).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.elementToBeClickable(By.id("checkoutLink")));
driver.findElement(By.id("checkoutLink")).click();
Run Code Online (Sandbox Code Playgroud)
但无论如何,最好的解决方案是依靠Selenide库,它处理这类事情等等.(而不是元素引用它处理代理,所以你永远不必处理过时的元素,这可能是非常困难的).硒
StaleElementReferenceException已经确定了发生这种情况的原因:在查找和使用元素执行某些操作之间更新DOM.
对于点击问题,我最近使用了这样的解决方案:
public void clickOn(By locator, WebDriver driver, int timeout)
{
final WebDriverWait wait = new WebDriverWait(driver, timeout);
wait.until(ExpectedConditions.refreshed(
ExpectedConditions.elementToBeClickable(locator)));
driver.findElement(locator).click();
}
Run Code Online (Sandbox Code Playgroud)
最关键的部分是硒自己的"链" ExpectedConditions通过ExpectedConditions.refreshed().这实际上等待并检查在指定的超时期间是否刷新了有问题的元素,并另外等待元素变为可点击.
在我的项目中,我引入了 StableWebElement 的概念。它是 WebElement 的包装器,能够检测元素是否过时并找到对原始元素的新引用。我添加了一个辅助方法来定位返回 StableWebElement 而不是 WebElement 的元素,并且 StaleElementReference 的问题消失了。
public static IStableWebElement FindStableElement(this ISearchContext context, By by)
{
var element = context.FindElement(by);
return new StableWebElement(context, element, by, SearchApproachType.First);
}
Run Code Online (Sandbox Code Playgroud)
C# 代码可在我的项目页面上找到,但可以轻松移植到 java https://github.com/cezarypiatek/Tellurium/blob/master/Src/MvcPages/SeleniumUtils/StableWebElement.cs
| 归档时间: |
|
| 查看次数: |
147938 次 |
| 最近记录: |