Main principle
Wait for the right condition, not for an arbitrary amount of time.
A synchronization reference for Selenium tests that need to survive real-world loading delays and dynamic UI behavior.
Wait for the right condition, not for an arbitrary amount of time.
Thread.sleep() as a default tool. It slows tests and still misses the real readiness signal.
Use explicit waits for important interactions and assertions.
Use clean locators and clean waits together. One without the other still flakes.
Hard sleeps block execution whether the app is ready or not.
// Avoid as a default strategy Thread.sleep(5000);
Implicit wait applies globally to element lookup, but it is blunt and limited.
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
Explicit waits are targeted and usually the most useful default for UI automation.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement button = wait.until(
ExpectedConditions.elementToBeClickable(By.id("submit"))
);
Choose the condition that matches what the test really needs next.
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("email")));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("email")));
These conditions cover most dynamic UI cases.
ExpectedConditions.elementToBeClickable(locator);
ExpectedConditions.textToBe(locator, "Success");
ExpectedConditions.urlContains("dashboard");
ExpectedConditions.alertIsPresent();
Fluent wait is helpful when you need custom polling and exception handling.
Waitwait = new FluentWait<>(driver) .withTimeout(Duration.ofSeconds(20)) .pollingEvery(Duration.ofMillis(500)) .ignoring(NoSuchElementException.class);
Use custom conditions when the built-in ones do not model the readiness you need.
wait.until(driver ->
driver.findElement(By.id("status")).getText().equals("Completed")
);
Re-find elements after DOM changes instead of holding stale references too long.
wait.until(ExpectedConditions.stalenessOf(oldElement));
WebElement fresh = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".updated-card"))
);
Target the exact event that makes the next step safe.
// good pattern
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.className("spinner")));
wait.until(ExpectedConditions.elementToBeClickable(By.id("continue")));