gpt4 book ai didi

java - Selenium:循环遍历一组元素时如何避免 StaleElementReferenceException?

转载 作者:行者123 更新时间:2023-11-30 10:01:17 26 4
gpt4 key购买 nike

我有一个包含一堆表格的页面。我在外循环中遍历表,然后在内循环中遍历表中的每一行。一切正常。但是有些页面有下一步按钮。当我在完成页面后添加代码以单击它时,我开始在循环遍历表格的行时收到 StaleElementReferenceException。

代码如下:

WebDriverWait wait1 = new WebDriverWait(driver, 10000);
WebElement maxPage = null;
WebElement auctionsWaitingDiv = driver.findElement(By.cssSelector("div[class='Head_W']"));
if (auctionsWaitingDiv.isDisplayed() == false) return properties;

try {
maxPage = wait1.until(ExpectedConditions.visibilityOfElementLocated(By.id("maxWA")));
} catch (TimeoutException ex) {
return properties;
}

Integer maxPageNo = 1;
if (!maxPage.getText().isEmpty())
maxPageNo = Integer.parseInt(maxPage.getText());
for (int i = 1; i <= maxPageNo; i++) {
driver.findElement(By.cssSelector("div[id='Area_W']")); //only look at Auctions Waiting section
WebDriverWait wait2 = new WebDriverWait(driver, 10000);
List<WebElement> tables = null;
try {
tables = wait2.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("table[class='ad_tab']")));
} catch (TimeoutException ex) {
System.out.println("table not found in allotted time");
return properties;
} catch (StaleElementReferenceException ex) {
System.out.println("returning due to StaleElementReferenceException");
return properties;

}
for (WebElement table: tables) {
List<String> propAttributes = new ArrayList<>();

// StaleElementReferenceException: The element reference of
// <table class="ad_tab"> is stale; either the element is no
// longer attached to the DOM, it is not in the current
// frame context, or the document has been refreshed
List<WebElement> rows = table.findElements(By.cssSelector("tr"));

String parcelLink = "";
for (WebElement row : rows) {
WebElement key = row.findElement(By.cssSelector("th"));
WebElement val = row.findElement(By.cssSelector("td"));
String keyVal = key.getText() + val.getText();
propAttributes.add(keyVal);
if (key.getText().equals("Parcel ID:")) {
WebElement a = val.findElement(By.cssSelector("a"));
parcelLink = a.getAttribute("href");
}
}
}
driver.findElement(By.xpath(".//*[@class='PageRight']")).click(); //click the "Next" button
}

我不明白为什么陈旧的元素会发生?页面在循环期间没有改变,我一直等到所有元素都被获取。如何避免 StaleElementReferenceException?

编辑:最后的堆栈跟踪显示它发生在这一行:

List<WebElement> rows = table.findElements(By.cssSelector("tr"));

上面的错误信息显示:

SEVERE: null

org.openqa.selenium.StaleElementReferenceException: The element reference of <table class="ad_tab"> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed

最佳答案

StaleElementReferenceException每当你想访问一个不再可用的元素引用时抛出。当元素不再附加到 DOM 或页面已更新时,就会发生这种情况。

解决方法就是每当发生这种情况时再次搜索该元素。您可以调整所有测试或页面对象。或者您编写自己的 RobustWebDriver 和 RobustWebElement,它们会在抛出 SERE 时刷新元素。

RobustWebDriver:

public class RobustWebDriver implements WebDriver {

private WebDriver originalWebDriver;

public RobustWebDriver(WebDriver webDriver) {
this.originalWebDriver = webDriver;
}

@Override
public void get(String url) {
this.originalWebDriver.get(url);
}

@Override
public String getCurrentUrl() {
return this.originalWebDriver.getCurrentUrl();
}

@Override
public String getTitle() {
return this.originalWebDriver.getTitle();
}

@Override
public List<WebElement> findElements(By by) {
List<WebElement> elements = new ArrayList<>();
for (WebElement element : this.originalWebDriver.findElements(by)) {
elements.add(new RobustWebElement(element, by, this));
}
return elements;
}

@Override
public WebElement findElement(By by) {
return new RobustWebElement(this.originalWebDriver.findElement(by), by, this);
}

@Override
public String getPageSource() {
return this.originalWebDriver.getPageSource();
}

@Override
public void close() {
this.originalWebDriver.close();

}

@Override
public void quit() {
this.originalWebDriver.quit();
}

@Override
public Set<String> getWindowHandles() {
return this.originalWebDriver.getWindowHandles();
}

@Override
public String getWindowHandle() {
return this.originalWebDriver.getWindowHandle();
}

@Override
public TargetLocator switchTo() {
return this.originalWebDriver.switchTo();
}

@Override
public Navigation navigate() {
return this.originalWebDriver.navigate();
}

@Override
public Options manage() {
return this.originalWebDriver.manage();
}
}

RobustWebElement:

public class RobustWebElement implements WebElement {

private WebElement originalElement;
private RobustWebDriver driver;
private By by;
private static final int MAX_RETRIES = 10;

public RobustWebElement(WebElement element, By by, RobustWebDriver driver) {
this.originalElement = element;
this.by = by;
this.driver = driver;
}

@Override
public void click() {
int retries = 0;
while (retries < MAX_RETRIES) {
try {
this.originalElement.click();
return;
} catch (StaleElementReferenceException ex) {
refreshElement();
}
retries++;
}
throw new StaleElementReferenceException(
String.format("Element is still stale after %s retries.", MAX_RETRIES));
}

@Override
public void sendKeys(CharSequence... keysToSend) {
int retries = 0;
while (retries < MAX_RETRIES) {
try {
this.originalElement.sendKeys(keysToSend);
return;
} catch (StaleElementReferenceException ex) {
refreshElement();
}
retries++;
}
throw new StaleElementReferenceException(
String.format("Element is still stale after %s retries.", MAX_RETRIES));
}

// TODO add other unimplemented methods with similar logic.

private void refreshElement() {
this.originalElement = driver.findElement(by);
}

然后您只需要将您的 WebDriver 包装到 RobustWebDriver 中就可以了:

WebDriver driver = new RobustWebDriver(new ChromeDriver());

编辑:

当然你需要自己照顾上下滚动。

关于java - Selenium:循环遍历一组元素时如何避免 StaleElementReferenceException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57512299/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com