1

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")));
NarendraR
  • 7,577
  • 10
  • 44
  • 82
Altober
  • 956
  • 2
  • 14
  • 28

2 Answers2

2

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.

Community
  • 1
  • 1
Cyril
  • 2,376
  • 16
  • 21
  • Thanks a lot for your answer I took your last suggestion. I somehow hack it with some other changes (see above). I am not 100% happy but it that the job. – Altober Jan 22 '17 at 15:58
2

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.

Moshisho
  • 2,781
  • 1
  • 23
  • 39
  • 1
    @Altober, have a look at this solution, it seems perfect. – Grzegorz Górkiewicz Jan 22 '17 at 18:36
  • Hi, Thanks a lot. I tried that but for some reason, after a couple of iterations, the execution hangs in the for loop. I will keep exploring and bring some update. – Altober Jan 22 '17 at 21:22
  • 1
    Thanks @Grzegorz made my day ;). As for the hanging, I assume it's because you have lots of elements from the `a` tag, and it polls the DOM for each of these... So if you can narrow down the list by using a more specific locator I assume it will help. i.e. `By.cssSelector("a.someClass")` – Moshisho Jan 23 '17 at 17:41