问题
我希望它只是我,但Selenium Webdriver似乎是一场彻头彻尾的噩梦。 Chrome webdriver目前无法使用,而其他驱动程序则非常不可靠,或者看起来如此。我正在与许多问题作斗争,但这里有一个问题。
随机地,我的测试将失败
"org.openqa.selenium.StaleElementReferenceException: Element is no longer attached
to the DOM
System info: os.name: 'Windows 7', os.arch: 'amd64',
os.version: '6.1', java.version: '1.6.0_23'"
我正在使用webdriver版本2.0b3。我已经看到FF和IE驱动程序发生这种情况。我可以阻止这种情况的唯一方法是在发生异常之前添加实际调用Thread.sleep
。这是一个糟糕的解决方法,所以我希望有人可以指出我的错误,这将使这一切变得更好。
#1 热门回答(111 赞)
是的,如果你遇到StaleElementReferenceExceptions问题,那是因为你的测试编写得很糟糕。这是一场竞争。请考虑以下情形:
WebElement element = driver.findElement(By.id("foo"));
// DOM changes - page is refreshed, or element is removed and re-added
element.click();
现在,在你单击元素的位置,元素引用不再有效。 WebDriver几乎不可能对可能发生这种情况的所有情况做出很好的猜测 - 所以它会抛出手并控制你,因为测试/应用程序作者应该确切知道可能会发生什么或不会发生什么。你要做的是明确等待,直到DOM处于你不知道事情不会改变的状态。例如,使用WebDriverWait等待特定元素存在:
// times out after 5 seconds
WebDriverWait wait = new WebDriverWait(driver, 5);
// while the following loop runs, the DOM changes -
// page is refreshed, or element is removed and re-added
wait.until(presenceOfElementLocated(By.id("container-element")));
// now we're good - let's click the element
driver.findElement(By.id("foo")).click();
presenceOfElementLocated()方法看起来像这样:
private static Function<WebDriver,WebElement> presenceOfElementLocated(final By locator) {
return new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
};
}
你对目前的Chrome驱动程序非常不稳定感到非常正确,你会很高兴听到Selenium主干有一个重写的Chrome驱动程序,其中大部分实现都是由Chromium开发人员完成的。
PS。或者,你可以启用隐式等待,而不是像上面的示例中那样显式等待 - 这样WebDriver将始终循环直到指定的超时等待元素出现:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)
根据我的经验,明确等待总是更可靠。
#2 热门回答(9 赞)
我已经能够使用这样的方法取得了一些成功:
WebElement getStaleElemById(String id) {
try {
return driver.findElement(By.id(id));
} catch (StaleElementReferenceException e) {
System.out.println("Attempting to recover from StaleElementReferenceException ...");
return getStaleElemById(id);
}
}
是的,它只是继续轮询元素,直到它不再被认为陈旧(新鲜?)。并没有真正找到问题的根源,但我发现WebDriver可能会相当挑剔抛出这个异常 - 有时候我会得到它,有时候我没有。或者可能是DOM真的在变化。
所以我不完全同意上面的答案,这必然表明一个写得不好的测试。我已经把它放在新页面上,我没有以任何方式与之互动。我认为在DOM的表示方式或者WebDriver认为过时的方式都存在一些瑕疵。
#3 热门回答(7 赞)
当AJAX更新处于中途时,我有时会收到此错误。 Capybara似乎非常聪明地等待DOM更改(参见Why wait_until was removed from Capybara),但在我的情况下,默认的2秒等待时间是不够的。已更改_spec_helper.rb_,例如
Capybara.default_wait_time = 5