Selenium:如何判断 RemoteWebDriver.findElements(By) 是否可以抛出 StaleElementReferenceException?
据我了解这样的异常可以抛出仅当代码在 WebElement
实例上运行时,在相应的 DOM 元素被重新加载或删除后调用其上的方法.
In my understanding such exception can be thrown only if the code operates on a WebElement
instance, calling methods on it after the corresponding DOM element has been reloaded or removed.
所以为了确定 RemoteWebDriver.findElements(By)
是否可以抛出该异常,我在 RemoteWebDriver
实现的源代码中查找了这种代码WebDriver
接口(在 selenium-remote-driver-3.8.1.jar
中).但是,深入了解RemoteWebDriver
的代码的调用堆栈最终对我来说变得太难了.
So in order to find out if RemoteWebDriver.findElements(By)
can throw that exception or not I looked for that kind of code in the source of the RemoteWebDriver
implementation of WebDriver
interface (in selenium-remote-driver-3.8.1.jar
). But following the call stacks deep down into RemoteWebDriver
's code eventually became too difficult for me.
所以我的问题是:除了试图通过检查 Selenium 源来弄清楚这一点之外,还有更好的方法来判断一般是 WebDriver
方法 - 还是只是 findElements(By)
特别是 - 可以抛出 StaleElementReferenceException
吗?这是一个 RuntimeException
,而 Selenium JavaDoc 没有 @throws
.
So my question is: besides trying to figure that out by inspecting Selenium source, are there better ways to tell if a WebDriver
method in general - or just findElements(By)
in particular - can throw StaleElementReferenceException
? It's a RuntimeException
, and the Selenium JavaDoc doesn't have @throws
for it.
推荐答案
您指出了有关StaleElementReferenceException"的问题,这与 webElement 实例更改时有关,当 DOM 因页面上的某些活动而更改时.
You pinpointed issue about "StaleElementReferenceException", this is related when webElement instances changes, when DOM is changed due some activity on page.
这与 WebDriver 如何在内部处理对 webElements 的引用有关,并且在运行时对对象的引用发生更改时会发生此问题.
It is related to how WebDriver internally handles references to webElements, and this issue happens when during runtime references to object(s) are changed.
现在,让我们假设当您获取元素并且在对其执行任何操作之前,页面上的某些内容已刷新.它可能是正在刷新的整个页面,也可能是某个调用仅刷新了元素所在的 DOM 的一部分.
Now, let’s assume when you have fetched the element and before doing any action on it, something got refreshed on your page. It could be the whole page that is being refreshed or some call which has refreshed only a section of the DOM where your element falls.
在这种情况下,WebDriver 使用并存储在缓存中某处的内部 id 已经过时(不再引用),因此现在对于此 WebElement 上的每个操作,我们都会得到 StaleElementReferenceException
.
In this scenario the internal id which WebDriver was using, and stored somewhere in cache has become stale (not referenced anymore), so now for every operation on this WebElement, we will get StaleElementReferenceException
.
所以要尽量避免在关键位置尝试使用这种方法,以确定元素是否过时.
So to try to avoid it on critical places try to use this method, for determine if element is stale.
public static boolean isStale(WebElement e){
try{
e.isDisplayed();
return false;
}catch(StaleElementReferenceException ex){
return true;
}
}
在 90% 的情况下,通常刷新页面、pageObject 或仅此特定元素会有所帮助.
Usually refreshing of page, pageObject, or just this particular element would help in 90% of cases.
并且在刷新页面/元素后,WebDriver 会为这个元素分配一个不同的内部 Id,并且可以再次使用它而不会出现任何问题.
And after refreshing page/element WebDriver will assign a different internal Id to this element, and will be able to use it again without any problem.
这个问题是 PageObject/PageFactory 设计模式的解决者.
This problem is solver with PageObject / PageFactory design patter.
public class SomePage {
@FindBy(how = How.NAME, using = "q")
private WebElement searchBox;
public SomePage() {
PageFactory.initElements(driver, this);
}
public void searchFor(String text) {
searchBox.sendKeys(text);
}
}
希望这会有所帮助,
相关文章