Avoiding StaleElementException in WebDriver
An important thing to remember is if you get a WebElement in Selenium WebDriver and the DOM changes (usually due to javascript), that WebElement will go stale. Any attempt to access it will cause a StaleElementException.
The most common reason for this to happen is getting a list of WebElements and iterating over them. The bigger the list the greater the change the DOM will change before you process all of them.
For example, if I have a table with id='mytable' and I want to iteration over all cells in the first column I might think this works:
List<WebElement> cells = driver.findElements(By.cssSelector("table#mytable>tbody>tr>td[1]"));
for(WebElement cell : cells) {
System.out.println(cell.getText());
}
If there are 100 rows, this will get a list of 100 WebElement. If the DOM changes before you get to element 100 you get a StaleElementException. To fix this, get one element at a time, use it then get the next. That is:
int size = driver.findElements(By.cssSelector("table#mytable>tbody>tr>td[1]")).size();
for(int i = 1; i <= size; i++) {
String locator = String.format("table#mytable>tbody>tr[%d]>td[1]", i);
WebElement cell = driver.findElement(By.cssSelector(locator));
System.out.println(cell.getText());
}
So rather than iterating over the list of WebElement (which can go stale), I iterating over the list of locator String (String doesn't go stale) and get one WebElement at a time.