End to end testing will always have a certain amount of flakiness. If you work on a single app or website full time then you start to figure out the characteristics of it and how to deal with them. Timing issues is usually the problem for myself... But getting to know how to use the WebDriverWait
class with ExpectedConditions
helps dramatically since it lets you make on call reactive wait conditions.
Pay attention to what the DOM is doing during an action, not just the element directly, but the elements around it too. If clicking a button causes the surrounding DOM to do stuff, then creating wait conditions for those other elements as part of your delay might be necessary.
One final suggestion on the topic of timing. Look up how to write your own ExpectedConditions
methods. You can write custom tailored conditions to wait on. This gives you a lot of flexibility for those little timing issues you always run into, but can't find a convenient solution prepared by Webdriver.
An example for writing your own custom expected conditions:
public static ExpectedCondition<Boolean> exampleCondition(final WebElement anElement) {
return new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
// you can do something with anElement here. If false is returned, the condition
// is not satisfied and this method will be invoked again and again until either
// true is returned, or the time limit is exceeded.
}
@Override
public String toString() {
return "I am a condition";
}
};
}
Any parameter can be defined as long as it's final, and can be used inside your anonymous implementation.
You can use this like so:
new WebDriverWait(driver, secondsToWait).until(MyExpectedConditions.exampleCondition(someWebElement));