遍历 WebElements 列表时获取 StaleElementReferenceException
Getting StaleElementReferenceException when iterating through a list of WebElements
我试图自动化以下场景:
- 转到amazon.com
- 搜索耳机
- 将第一个结果页面中的所有畅销书添加到购物车
我编写此场景脚本所遵循的步骤:
- 转到amazon.com
- 在搜索字段中输入文本 "headphones"
- 点击搜索按钮
- 单击标记为 'bestseller'
的 link
- 单击 'add to cart' 按钮
- 导航回结果页面
- 单击另一个标记为 'bestseller'
的 link
- 单击 'add to cart' 按钮
- 导航回结果页面
所有畅销书都有相同的 xpath:
//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span
所以我实现了这个 WebElements 列表,如下所示:
List<WebElement> bestsellers = driver.findElements(By.xpath("xpath of bestsellers"));
我已经通过以下 3 种方式实现了点击 link 并使用循环添加到购物车:
for(WebElement product: bestsellers) {
product.click();
clickOnAddToCartButton();
driver.navigate().back();
}
for(int i=0; i<bestsellers.size(); i++) {
System.out.println(bestsellers.size());
bestsellers.get(i).click();
clickOnAddToCartButton();
driver.navigate().back();
}
Iterator<WebElement> i = bestsellers.iterator();
while(i.hasNext()) {
WebElement product = i.next();
wait.until(ExpectedConditions.elementToBeClickable(product));
product.click();
clickOnAddToCartButton();
driver.navigate().back();
}
列表中有 3 个元素 'bestsellers' 当我有 运行 脚本时。当循环执行时,第一个元素被点击并添加到购物车,驱动程序导航回结果页面。然后我使用上述 3 种方式得到 staleElementReferenceException。
更新:
我已经按如下方式实现了场景:
for(int i=0; i<bestsellers.size(); i++) {
System.out.println("Current :" + i);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(".//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span")));
driver.findElements(By.xpath(".//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span")).get(i).click();
clickOnAddToCartButton();
//clickOnViewCart();
try {
wait.until(ExpectedConditions.elementToBeClickable(cartButton));
}catch(TimeoutException e) {
wait.until(ExpectedConditions.elementToBeClickable(viewCartButton));
}
if(i==(bestsellers.size()-1)) {
try {
wait.until(ExpectedConditions.elementToBeClickable(cartButton));
cartButton.click();
break;
}catch(TimeoutException e) {
wait.until(ExpectedConditions.elementToBeClickable(viewCartButton));
viewCartButton.click();
break;
}
}
driver.navigate().back();
当您在浏览器中单击元素或 back() 时,元素引用将在 selenium 中更新,因此您无法指向具有旧引用的元素,这导致了 StatleElementException
。
当您必须遍历多个元素交互时,请考虑这种方法。
List<WebElement> bestsellers = driver.findElements(By.xpath("xpath of bestsellers"));
for(int i=0; i<bestsellers.size(); i++) {
System.out.println("Current Seller " + i);
// here you are getting the elements each time you iterate, which will get the
// latest element references
driver.findElements(By.xpath("xpath of bestsellers")).get(i).click();
clickOnAddToCartButton();
driver.navigate().back();
}
我试图自动化以下场景:
- 转到amazon.com
- 搜索耳机
- 将第一个结果页面中的所有畅销书添加到购物车
我编写此场景脚本所遵循的步骤:
- 转到amazon.com
- 在搜索字段中输入文本 "headphones"
- 点击搜索按钮
- 单击标记为 'bestseller' 的 link
- 单击 'add to cart' 按钮
- 导航回结果页面
- 单击另一个标记为 'bestseller' 的 link
- 单击 'add to cart' 按钮
- 导航回结果页面
所有畅销书都有相同的 xpath:
//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span
所以我实现了这个 WebElements 列表,如下所示:
List<WebElement> bestsellers = driver.findElements(By.xpath("xpath of bestsellers"));
我已经通过以下 3 种方式实现了点击 link 并使用循环添加到购物车:
for(WebElement product: bestsellers) {
product.click();
clickOnAddToCartButton();
driver.navigate().back();
}
for(int i=0; i<bestsellers.size(); i++) {
System.out.println(bestsellers.size());
bestsellers.get(i).click();
clickOnAddToCartButton();
driver.navigate().back();
}
Iterator<WebElement> i = bestsellers.iterator();
while(i.hasNext()) {
WebElement product = i.next();
wait.until(ExpectedConditions.elementToBeClickable(product));
product.click();
clickOnAddToCartButton();
driver.navigate().back();
}
列表中有 3 个元素 'bestsellers' 当我有 运行 脚本时。当循环执行时,第一个元素被点击并添加到购物车,驱动程序导航回结果页面。然后我使用上述 3 种方式得到 staleElementReferenceException。
更新: 我已经按如下方式实现了场景:
for(int i=0; i<bestsellers.size(); i++) {
System.out.println("Current :" + i);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(".//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span")));
driver.findElements(By.xpath(".//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span")).get(i).click();
clickOnAddToCartButton();
//clickOnViewCart();
try {
wait.until(ExpectedConditions.elementToBeClickable(cartButton));
}catch(TimeoutException e) {
wait.until(ExpectedConditions.elementToBeClickable(viewCartButton));
}
if(i==(bestsellers.size()-1)) {
try {
wait.until(ExpectedConditions.elementToBeClickable(cartButton));
cartButton.click();
break;
}catch(TimeoutException e) {
wait.until(ExpectedConditions.elementToBeClickable(viewCartButton));
viewCartButton.click();
break;
}
}
driver.navigate().back();
当您在浏览器中单击元素或 back() 时,元素引用将在 selenium 中更新,因此您无法指向具有旧引用的元素,这导致了 StatleElementException
。
当您必须遍历多个元素交互时,请考虑这种方法。
List<WebElement> bestsellers = driver.findElements(By.xpath("xpath of bestsellers"));
for(int i=0; i<bestsellers.size(); i++) {
System.out.println("Current Seller " + i);
// here you are getting the elements each time you iterate, which will get the
// latest element references
driver.findElements(By.xpath("xpath of bestsellers")).get(i).click();
clickOnAddToCartButton();
driver.navigate().back();
}