尝试从日期选择器中选择日期时如何修复 'stale element reference exception'?
How to fix 'stale element reference exception' while trying to pick date from date-picker?
我正在尝试从 Datepicker 获取 select 日期。以下是代码
WebDriver d=new FirefoxDriver();
Actions a=new Actions(d);
String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
for(WebElement tr:trs) {
List<WebElement> tds=tr.findElements(By.tagName("td"));
for(WebElement td:tds) {
if(date.equals(td.getText())) {
a.moveToElement(td).click().build().perform();
}
}
}
使用上面的代码,我在这行代码中得到了陈旧的元素引用异常
"if(date.equals(td.getText())) {"
所以我把代码改成了这个
for(WebElement td:tds) {
while(i<4) {
try {
if(date.equals(td.getText())) {
a.moveToElement(td).click().build().perform();
}
break;
}catch(Exception ex) {
}
System.out.println(i);
i++;
}
}
现在我可以 select date.But 脚本仍在抛出陈旧的元素引用 exception.The 脚本现在在这一行显示错误
List<WebElement> tds=tr.findElements(By.tagName("td"));
我正在处理过去 3 days.Any 条关于如何解决此问题的建议。
提前致谢
根据我的理解,当您在 for 循环 DOM 中执行 element.click() 时重新加载,这就是它显示陈旧元素异常的原因。
使用以下 css select 或 [它将 selected 仅来自预期日期选择器的元素,使用它是因为页面上有多个日期选择器 ] 并在匹配日期上应用 break in for 循环,例如below.It 将 select 日期为 14 并毫无例外地打破循环 -
String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector(".datepicker.dropdown-menu:nth-of-type(4)>div.datepicker-days>table>tbody>tr>td"));
for(WebElement td:trs) {
if(date.equals(td.getText())) {
td.click();
break;
}
}
在您的第一个代码中,在您单击该元素后,DOM 发生了变化,因为日期变为 "14",并且由于两个 for 循环仍在迭代,因此它抛出 StaleElementReferenceException。
同样,在第二个代码中,您确实破坏了迭代 td[=36= 的 "inside for-loop" ] 元素,但您没有破坏 "outside" 元素,它继续迭代 tr 个元素,因此它再次抛出 StaleElementReferenceException。
解决方案:- 你应该 使用 break[=37 退出两个 for 循环=] 在元素被点击后,因此 避免 StaleElementReferenceException,在这个过程中。
下面的代码显示了如何毫无例外地突破两个 for 循环:
WebDriver d=new FirefoxDriver();
d.manage().window().maximize(); //Maximizing window
d.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); //Implicit wait for 20 seconds
Actions a=new Actions(d);
String date="14";
int flag=0;
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
for(WebElement tr:trs) {
List<WebElement> tds=tr.findElements(By.tagName("td"));
for(WebElement td:tds) {
if(date.equals(td.getText())) {
a.moveToElement(td).click().build().perform();
flag=1; // Set to 1 when the required element was found and clicked.
break; //To come out of the first for-loop
}
}
if(flag==1)
break; //Since the element was found, come out of the second for-loop.
}
注意:- 我已经添加了用于最大化 windows 并提供隐式等待的代码,这实际上是您在编写 selenium 脚本时建议的。
您应该使用 WebDriverWait
和 ExpectedConditions
来解决元素的陈旧问题。下面是我测试过的修改后的代码块。
driver.findElement(By.cssSelector("div#dp3>span")).click();
WebDriverWait wait = new WebDriverWait(driver, 30);
List<WebElement> trs = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.cssSelector("div.datepicker-days>table>tbody>tr")));
datePicker:
{
for (WebElement tr : trs) {
List<WebElement> tds = tr.findElements(By.tagName("td"));
for (WebElement td : tds) {
wait.until(ExpectedConditions.not(ExpectedConditions.stalenessOf(td)));
if (date.equals(td.getText())) {
td.click();
break datePicker;
}
}
}
}
有关详细信息,请查看 WebDriverWait and ExpectedConditions 此处
找到了一种更简单的方法来解决我的陈旧元素引用异常。
在 Java 中使用 Selenium2 尝试下面的代码:
public WebElement cleanAndRebuildElement(final WebElement ee) {
WebElement e2;
try {
e2=ee;
e2.isDisplayed();
logger.info("Element is cleaned : Not Stale Anymore !");
} catch (StaleElementReferenceException e) {
e2=null;
} catch(NoSuchElementException nse) {
nse.printstacktrace();
}
return e2;
}
}
我正在尝试从 Datepicker 获取 select 日期。以下是代码
WebDriver d=new FirefoxDriver();
Actions a=new Actions(d);
String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
for(WebElement tr:trs) {
List<WebElement> tds=tr.findElements(By.tagName("td"));
for(WebElement td:tds) {
if(date.equals(td.getText())) {
a.moveToElement(td).click().build().perform();
}
}
}
使用上面的代码,我在这行代码中得到了陈旧的元素引用异常
"if(date.equals(td.getText())) {"
所以我把代码改成了这个
for(WebElement td:tds) {
while(i<4) {
try {
if(date.equals(td.getText())) {
a.moveToElement(td).click().build().perform();
}
break;
}catch(Exception ex) {
}
System.out.println(i);
i++;
}
}
现在我可以 select date.But 脚本仍在抛出陈旧的元素引用 exception.The 脚本现在在这一行显示错误
List<WebElement> tds=tr.findElements(By.tagName("td"));
我正在处理过去 3 days.Any 条关于如何解决此问题的建议。 提前致谢
根据我的理解,当您在 for 循环 DOM 中执行 element.click() 时重新加载,这就是它显示陈旧元素异常的原因。 使用以下 css select 或 [它将 selected 仅来自预期日期选择器的元素,使用它是因为页面上有多个日期选择器 ] 并在匹配日期上应用 break in for 循环,例如below.It 将 select 日期为 14 并毫无例外地打破循环 -
String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector(".datepicker.dropdown-menu:nth-of-type(4)>div.datepicker-days>table>tbody>tr>td"));
for(WebElement td:trs) {
if(date.equals(td.getText())) {
td.click();
break;
}
}
在您的第一个代码中,在您单击该元素后,DOM 发生了变化,因为日期变为 "14",并且由于两个 for 循环仍在迭代,因此它抛出 StaleElementReferenceException。
同样,在第二个代码中,您确实破坏了迭代 td[=36= 的 "inside for-loop" ] 元素,但您没有破坏 "outside" 元素,它继续迭代 tr 个元素,因此它再次抛出 StaleElementReferenceException。
解决方案:- 你应该 使用 break[=37 退出两个 for 循环=] 在元素被点击后,因此 避免 StaleElementReferenceException,在这个过程中。
下面的代码显示了如何毫无例外地突破两个 for 循环:
WebDriver d=new FirefoxDriver();
d.manage().window().maximize(); //Maximizing window
d.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); //Implicit wait for 20 seconds
Actions a=new Actions(d);
String date="14";
int flag=0;
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
for(WebElement tr:trs) {
List<WebElement> tds=tr.findElements(By.tagName("td"));
for(WebElement td:tds) {
if(date.equals(td.getText())) {
a.moveToElement(td).click().build().perform();
flag=1; // Set to 1 when the required element was found and clicked.
break; //To come out of the first for-loop
}
}
if(flag==1)
break; //Since the element was found, come out of the second for-loop.
}
注意:- 我已经添加了用于最大化 windows 并提供隐式等待的代码,这实际上是您在编写 selenium 脚本时建议的。
您应该使用 WebDriverWait
和 ExpectedConditions
来解决元素的陈旧问题。下面是我测试过的修改后的代码块。
driver.findElement(By.cssSelector("div#dp3>span")).click();
WebDriverWait wait = new WebDriverWait(driver, 30);
List<WebElement> trs = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.cssSelector("div.datepicker-days>table>tbody>tr")));
datePicker:
{
for (WebElement tr : trs) {
List<WebElement> tds = tr.findElements(By.tagName("td"));
for (WebElement td : tds) {
wait.until(ExpectedConditions.not(ExpectedConditions.stalenessOf(td)));
if (date.equals(td.getText())) {
td.click();
break datePicker;
}
}
}
}
有关详细信息,请查看 WebDriverWait and ExpectedConditions 此处
找到了一种更简单的方法来解决我的陈旧元素引用异常。
在 Java 中使用 Selenium2 尝试下面的代码:
public WebElement cleanAndRebuildElement(final WebElement ee) {
WebElement e2;
try {
e2=ee;
e2.isDisplayed();
logger.info("Element is cleaned : Not Stale Anymore !");
} catch (StaleElementReferenceException e) {
e2=null;
} catch(NoSuchElementException nse) {
nse.printstacktrace();
}
return e2;
}
}