如何处理 StaleElementReferenceException
How to handle StaleElementReferenceException
我有一个场景,我试图循环遍历条形图上的多个元素,直到找到 "rect" 标签名称。当我点击 "rect" 标签名称时,从图表中选择了单个柱,我被重定向到另一个页面。请在下面查看我正在使用的条形图的图像:
http://imgur.com/xU63X1Z
作为参考,我正在使用的条形图位于右上角。我要执行的测试是单击图表中的第一个柱;这样做,会将我重定向到适当的页面。为此,我使用 Eclipse (Java) 在 Selenium Webdriver 中编写了以下代码:
WebElement deliveredChartDailyFocus = driver.findElement(By.id("delivered-chart-daily"));
deliveredChartDailyFocus.click();
List<WebElement> children = deliveredChartDailyFocus.findElements(By.tagName("rect"));
Iterator<WebElement> iter = children.iterator();
while (iter.hasNext()) {
WebElement we = iter.next();
if(we.isDisplayed()){
we.click();
}
一切似乎都运行良好,因为上面的代码点击了“rect”元素并将我重定向到适当的页面。但是,当我点击该页面时,我会收到错误消息,因为代码仍在寻找不在新页面上的“rect”值。
你会注意到上面少了一个“break”行…..这是因为,在调试代码时我发现在遍历循环时,点击事件直到第三次迭代,我假设是因为“rect”元素不可见?因此,如果我放入一个“break”语句,它会在第一次迭代后退出循环,因此我永远不会到达执行“click”事件以导航到新页面的部分。
本质上,我所追求的是一种能够根据需要循环多次直到找到合适的“rect”元素的方法。单击该按钮后,我将被重定向到新页面……只有在那时我才希望循环退出,以便不显示“NoSuchElementException 错误。
如果需要任何更多详细信息,请告诉我,非常感谢对此的任何指导。
Andy,这里的问题是DOM
刷新。您不能简单地获取 IWebElements
的集合并遍历并来回单击。您 可以 找到元素的数量,并且每次您来到页面时都可以动态地找到您想要单击的元素。请参阅 this 以了解实施方式
public void ClickThroughLinks()
{
_driver.Navigate().GoToUrl("http://www.cnn.com/");
//Maximize the window so that the list can be gathered successfully.
_driver.Manage().Window.Maximize();
//find the list
By xPath = By.XPath("//h2[.='The Latest']/../li//a");
var linkCollection = _driver.FindElements(xPath);
for (int i = 0; i < linkCollection.Count; i++)
{
//wait for the elements to be exist
new WebDriverWait(_driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementExists(xPath));
//Click on the elements by index
if (i<=3)
{
_driver.FindElements(xPath)[i].Click();
}
else
{
break;
}
_driver.Navigate().Back();
_driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(10));
}
}
进入新页面后,所有这些 rect
元素都消失了。对那些 rect
元素执行任何引用都将触发此 StaleElementReferenceException
.
所以不要在点击后引用那些元素。迭代到第一个显示的 rect
元素然后停止迭代。
WebElement deliveredChartDailyFocus = driver.findElement(By.id("delivered-chart-daily"));
deliveredChartDailyFocus.click();
// Get a list of all the <rect> elements under the #delivered-chart-daily element
List<WebElement> children = deliveredChartDailyFocus.findElements(By.tagName("rect"));
WebElement elementToClick = null; // variable for the element we want to click on
for (WebElement we : children) // loop through all our <rect> elements
{
if (we.isDisplayed())
{
elementToClick = we; // save the <rect> element to our variable
break; // stop iterating
}
}
if (elementToClick != null) // check we have a visible <rect> element
{
elementToClick.click();
}
else
{
// Handle case if no displayed rect elements were found
}
我有一个场景,我试图循环遍历条形图上的多个元素,直到找到 "rect" 标签名称。当我点击 "rect" 标签名称时,从图表中选择了单个柱,我被重定向到另一个页面。请在下面查看我正在使用的条形图的图像: http://imgur.com/xU63X1Z
作为参考,我正在使用的条形图位于右上角。我要执行的测试是单击图表中的第一个柱;这样做,会将我重定向到适当的页面。为此,我使用 Eclipse (Java) 在 Selenium Webdriver 中编写了以下代码:
WebElement deliveredChartDailyFocus = driver.findElement(By.id("delivered-chart-daily"));
deliveredChartDailyFocus.click();
List<WebElement> children = deliveredChartDailyFocus.findElements(By.tagName("rect"));
Iterator<WebElement> iter = children.iterator();
while (iter.hasNext()) {
WebElement we = iter.next();
if(we.isDisplayed()){
we.click();
}
一切似乎都运行良好,因为上面的代码点击了“rect”元素并将我重定向到适当的页面。但是,当我点击该页面时,我会收到错误消息,因为代码仍在寻找不在新页面上的“rect”值。
你会注意到上面少了一个“break”行…..这是因为,在调试代码时我发现在遍历循环时,点击事件直到第三次迭代,我假设是因为“rect”元素不可见?因此,如果我放入一个“break”语句,它会在第一次迭代后退出循环,因此我永远不会到达执行“click”事件以导航到新页面的部分。
本质上,我所追求的是一种能够根据需要循环多次直到找到合适的“rect”元素的方法。单击该按钮后,我将被重定向到新页面……只有在那时我才希望循环退出,以便不显示“NoSuchElementException 错误。
如果需要任何更多详细信息,请告诉我,非常感谢对此的任何指导。
Andy,这里的问题是DOM
刷新。您不能简单地获取 IWebElements
的集合并遍历并来回单击。您 可以 找到元素的数量,并且每次您来到页面时都可以动态地找到您想要单击的元素。请参阅 this 以了解实施方式
public void ClickThroughLinks()
{
_driver.Navigate().GoToUrl("http://www.cnn.com/");
//Maximize the window so that the list can be gathered successfully.
_driver.Manage().Window.Maximize();
//find the list
By xPath = By.XPath("//h2[.='The Latest']/../li//a");
var linkCollection = _driver.FindElements(xPath);
for (int i = 0; i < linkCollection.Count; i++)
{
//wait for the elements to be exist
new WebDriverWait(_driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementExists(xPath));
//Click on the elements by index
if (i<=3)
{
_driver.FindElements(xPath)[i].Click();
}
else
{
break;
}
_driver.Navigate().Back();
_driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(10));
}
}
进入新页面后,所有这些 rect
元素都消失了。对那些 rect
元素执行任何引用都将触发此 StaleElementReferenceException
.
所以不要在点击后引用那些元素。迭代到第一个显示的 rect
元素然后停止迭代。
WebElement deliveredChartDailyFocus = driver.findElement(By.id("delivered-chart-daily"));
deliveredChartDailyFocus.click();
// Get a list of all the <rect> elements under the #delivered-chart-daily element
List<WebElement> children = deliveredChartDailyFocus.findElements(By.tagName("rect"));
WebElement elementToClick = null; // variable for the element we want to click on
for (WebElement we : children) // loop through all our <rect> elements
{
if (we.isDisplayed())
{
elementToClick = we; // save the <rect> element to our variable
break; // stop iterating
}
}
if (elementToClick != null) // check we have a visible <rect> element
{
elementToClick.click();
}
else
{
// Handle case if no displayed rect elements were found
}