简体   繁体   中英

Selenium StaleElementReferenceException

Hi I am new to Selenium

I am using the Java library , already tried both the Chrome and the Firefox drivers.

I am running a loop. The interesting thing is that the loop works sometimes 3, 2 times, it does not always fail in the same iteration. I assume it has to do with some sort of race condition (like waiting the page to load). If I run in debug mode it seems to work perfectly.

I already tried suggestions from other answers like to wait explicitly and implicitly but still not helping. Maybe if you see the code you can give me a hand.

This goes inside a loop.

WebDriverWait wait = new WebDriverWait(driver,20);
WebElement searchResults = driver.findElement(new By.ById("searchresults"));
searchResults = searchResults.findElement(new By.ByClassName("table"));
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.tagName("a")));
List<WebElement> list=searchResults.findElements(By.tagName("a"));
for(WebElement w: list) {
  result.add(w.getAttribute("href")); //EXCEPTION HAPPENS ALWAYS HERE
}

SOLUTION

The solution is a total hack. I still do not understand, but it does the job. If someone understands why please let me know.

I just move all the waits up and it performs better. I also took the suggestion of @Cyril to re-run the iteration if the exception was thrown along some data checks to make sure I got all I wanted.

WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(new By.ById("searchresults")));
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(new By.ByClassName("table"))); 
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.tagName("a")));

StaleElementReferenceException means that the DOM elements you are accessing got changed or removed from the DOM. So waiting until the elements are visible or present does not help (they still can get updated after that).

You can probably fix the exception by explicitly waiting for 5 seconds via Thread.sleep before you look up any DOM elements.

Another option is to look up the element again if the exception is thrown . But it only works well for single elements.

In order to avoid the StaleElementReferenceException you can get the attribute during the find element. Here's a snippet ( nth-child first index is 1):

List<WebElement> list=searchResults.findElements(By.tagName("a"));
for(int i = 1; i < list.length; i++) {
   result.add(searchResults.findElement(By.cssSelector("a:nth-child(" + i + ")")).getAttribute("href"));
}

That way the only chance for the exception is if the element changes between the findElement and the getAttribute which is unlikely (or the table element changes - searchResults ). Of course, there are better ways to achieve this like a wrapper function around findElement or using Page Object Pattern, but for your case it supposed to be sufficient.

EDIT: your solution probably works because it makes the script wait until the page is fully loaded and then the elements aren't changing anymore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM