Selenium is an open-source web-based automation tool. In web automation testing, Selenium WebDriver is the undisputed champion. It allows testers and developers to interact with web applications just like a real user. In this Answer, we will learn how to leverage these Selenium waits to make our testing more optimized and focused.
Let's take a moment to appreciate the significance of waits in automated testing. As Selenium interacts with web elements, it's crucial to ensure synchronization between the test script and the web page. Without proper waits, our tests may encounter flakiness, resulting in false positives or negatives.
At the heart of our Java Selenium framework lies the WebDriver interface, which provides methods for interacting with web elements. To implement waits, we enlist the WebDriverWait class, a powerful tool for handling different types of waits, such as implicit, explicit, and fluent waits.
Now, let's look into the different waiting strategies:
Implicit waits: Implicit waits instruct Selenium to wait for a specified amount of time before throwing a NoSuchElementException. While they are simple to implement, they apply globally to all elements and can potentially lead to longer test execution times.
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Explicit waits: Unlike implicit waits, explicit waits target specific conditions before proceeding with test execution. We can specify a maximum wait time and the conditions to wait for, ensuring precise synchronization.
WebDriverWait wait = new WebDriverWait(driver, 10);WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));
Fluent waits: With fluent waits, we define the polling interval and maximum wait time, allowing Selenium to wait dynamically until the desired condition is met.
Wait wait = new FluentWait(driver).withTimeout(Duration.ofSeconds(30)).pollingEvery(Duration.ofSeconds(5)).ignoring(NoSuchElementException.class);WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));
Custom waits: Tailoring waits to suit our specific testing needs can significantly enhance the reliability of our framework. Whether it's waiting for a loading spinner to disappear or for an AJAX call to complete, custom waits offer unparalleled flexibility.
WebDriverWait wait = new WebDriverWait(driver, 10);WebElement element = wait.until(driver -> driver.findElement(By.id("elementId")).isDisplayed());
Thread.sleep()
: This is used for simple, static wait requirements as it pauses the execution for a specified period. However, it is not recommended for dynamic web pages due to its inflexibility.
try {Thread.sleep(5000); // Sleep for 5 seconds} catch (InterruptedException e) {e.printStackTrace();}
Let’s try to understand these with the help of an illustration:
Let’s look at an example to understand these concepts in a better way:
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeDriverService; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import java.util.concurrent.TimeUnit; public class Main { public static void main(String[] args) { // Set ChromeDriver path System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver-linux64/chromedriver"); // Configuring and setting up the Browser ChromeOptions options = new ChromeOptions(); options.setBinary("/usr/bin/google-chrome"); options.addArguments("--no-sandbox"); options.addArguments("--disable-dev-shm-usage"); options.addArguments("--disable-gpu"); options.addArguments("--remote-debugging-port=9222"); ChromeDriverService service = new ChromeDriverService.Builder() .usingPort(9515) .build(); // Initialize Chrome WebDriver WebDriver driver = new ChromeDriver(service, options); driver.manage().window().maximize(); // Navigating to the website driver.get("https://www.python.org/"); // Implicit wait is set here driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); // Accessing the Documentation tab using partial link text String partialLinkText = "Docs"; WebElement element = driver.findElement(By.partialLinkText(partialLinkText)); element.click(); // Explicit wait for the page to load after clicking WebDriverWait wait = new WebDriverWait(driver, 20); wait.until(ExpectedConditions.urlContains("docs.python.org")); // Adding a delay to observe the actions try { Thread.sleep(20000); // Sleep for 20 seconds } catch (InterruptedException e) { e.printStackTrace(); } // Closing the WebDriver driver.quit(); } }
Let’s try to understand the given code:
Lines 1–8: We import the necessary libraries to make our script run seamlessly.
Lines 16–27: These are the configurations of our browser and web driver. We set all the necessary arguments here to ensure that the script executes without error.
Line 34: We navigate to our desired web page, i.e., (https://www.python.org/
) in our case, by using driver.get()
method.
Line 37: We set an implicit wait after navigating the web page. Here, the web driver will wait for 20 seconds before executing any other task.
Lines 40–42: Here, we explore the content of the page by using driver.findElement()
method. In this case, we navigate to the documentation page.
Lines 45–46: We set the explicit wait here based on the condition that the page loaded is indeed the documentation page.
Lines 49-53: Here is an example of Thread.sleep()
is shown that pauses the execution of the script for the defined time, 20 seconds in this case.
Line 56: At the end, we close the web driver by using driver.quit()
method.
While mastering waits is undoubtedly empowering, it's essential to adhere to best practices to maximize their effectiveness:
Keep waits short: Strive to keep the wait times as short as possible without compromising reliability. Long waits can lead to sluggish test execution and hinder overall efficiency.
Use expected conditions wisely: Leverage the extensive library of ExpectedConditions provided by Selenium to define precise conditions for waits. Whether it’s element visibility, staleness, or presence, there’s a condition for every scenario.
Handle timeouts gracefully: Incorporate error handling mechanisms to gracefully manage timeouts and handle exceptions that may arise during wait operations. This ensures smooth test execution even in challenging scenarios.
To sum up, with a solid understanding of intelligent waits and their implementation in Java Selenium frameworks, we are well-equipped to streamline our automation testing efforts. By understanding the workflow of wait handling, we can enhance the reliability, efficiency, and scalability of our tests, making the way for smoother and more reliable automation journeys.
Free Resources