WebDriverWait in Selenium Java: A Detailed Tutorial
Faisal Khatri
Posted On: October 23, 2024
219553 Views
13 Min Read
Handling dynamic web content can be challenging when automating websites using Selenium since web pages may load at different speeds. This is due to various reasons like dynamic loading or network delays and elements may appear asynchronously. As a result, tests can throw Selenium exceptions and become flaky and unreliable.
To handle these scenarios efficiently, Selenium provides the WebDriverWait class that can be used with programming languages such as Java. Using WebDriverWait in Selenium Java helps testers pause the test execution and wait for certain conditions to be met before proceeding to the next action. It also ensures the WebElement is available for any action before it is taken, providing stability to the tests and improving the pass percentage by preventing related failures.
In this blog, we dive deep into how to use WebDriverWait in Selenium Java.
TABLE OF CONTENTS
What Is WebDriverWait in Selenium?
There are different types of Selenium waits to handle various test scenarios. Among these, explicit waits can be implemented using the methods provided in the WebDriverWait class. These methods are enabled through some conditions where the driver waits for the specified condition to be fulfilled within the specified amount of wait time before proceeding further with the test execution.
It works by polling the Document Object Model (DOM) at regular intervals to check if the condition is met for the given WebElement within the specified timeout period. If the condition is met within the timeout, the script proceeds; otherwise, it throws a TimeoutException.
ExpectedConditions in Selenium are methods available in the ExpectedConditions class that are used in combination with the WebDriverWait class to define these pre-conditions and custom wait strategies. These conditions can be used in an easy-to-implement way in almost all programming languages including Java.
How to Use WebDriverWait in Selenium Java?
Having understood the Selenium WebDriverWait, let’s move forward and learn how to use WebDriverWait in Selenium Java in test scripts. We will cover some of the most commonly used explicit wait implementations using the ExpectedConditions.
In this blog on using WebDriverWait in Selenium Java, we will use RemoteWebDriver for test execution. Using RemoteWebDriver allows you to harness the capabilities of the cloud grid, including speedy and parallel test execution in a more organized way.
Let’s use LambdaTest, an AI-powered test execution platform that offers an online Selenium Grid, enabling developers and testers to perform automation testing for websites and web applications on a wide range of real browsers, devices, and operating system combinations.
Run Selenium tests on real browsers and operating systems.Try LambdaTest Today!
Setting Up Project
For demonstration purposes in this blog, let’s use Eclipse IDE. You can use any other of your choice, and do the project setup using the same steps.
- Create a new Maven Project and name it as WebDriverWait.
- Add a new package, Waits, under src/test/java package. This is the package in which we add our test classes to demonstrate the usage of different explicit waits using ExpectedConditions.
- Add Java class files inside this Waits package and name them as:
- TestBase.java: Contains the code to launch the browser by connecting to LambdaTest remote Selenium Grid and closing the browser.
- TestExplicitWait.java: Contains the test class file to demonstrate the implementation of WebDriverWait using different ExpectedConditions.
- TestFluentWait.java: Contains the test class file to demonstrate fluent wait implementation.
- Update the pom.xml file to have Selenium and TestNG dependencies. This is required as we are writing a web automation script using TestNG for test execution. Always use the latest stable versions of these dependencies for best execution results.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>WebDriverWait</groupId> <artifactId>WebDriverWait</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.23.1</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.10.2</version> <scope>test</scope> </dependency> </dependencies> </project> |
With this, our basic project setup is completed. Let’s move forward and have a look at the TestBase.java file.
To begin, create a RemoteWebDriver object and initialize it to null. You will need to include your LambdaTest Username and Access Key, which can be found in your Account Settings under the Password & Security tab. These credentials are used to connect to the LambdaTest cloud grid for test execution.
For added security, you can configure these values as environment variables instead of hardcoding them in the test script. Additionally, define a String variable called status and initialize it with the value failed. This status is updated to passed if the test case runs without any assertion failures or exceptions, ensuring the test’s final status is accurately reflected on the LambdaTest Web Automation dashboard.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public class TestBase { public RemoteWebDriver driver = null; String username = System.getenv("LT_USERNAME") == null ? "<lambdatest_username>" : System.getenv("LT_USERNAME"); String accessKey = System.getenv("LT_ACCESS_KEY") == null ? "<lambdatest_accesskey>" : System.getenv("LT_ACCESS_KEY"); String status = "failed"; @BeforeMethod public void setUp() { try { ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.setPlatformName("Windows 10"); chromeOptions.setBrowserVersion("127.0"); HashMap<String, Object> ltOptions = new HashMap<String, Object>(); ltOptions.put("build", "WebDriverWaits in Selenium Java"); ltOptions.put("name", "WebDriverWaits in Selenium Java"); chromeOptions.setCapability("LT:Options", ltOptions); driver = new RemoteWebDriver( new URL("https://" + username + ":" + accessKey + "@hub.lambdatest.com/wd/hub"), chromeOptions); } catch (MalformedURLException e) { e.printStackTrace(); } } |
Next, create a setup() method, annotated with @BeforeMethod annotation from TestNG, to handle setting up browser properties and LambdaTest configurations before each test case. Use the LambdaTest Automation Capabilities Generator to fetch the required browser capabilities.
Then, connect to LambdaTest using RemoteWebDriver and a ChromeOptions object containing all the specified browser settings. After each test execution, a tearDown() method, annotated with @AfterMethod, will update the test status on LambdaTest and close the WebDriver. The main test class, TestExplicitWait, extends TestBase to inherit properties and methods required for the tests.
Writing Tests
The TestExplicitWait class contains 4 different test methods to demonstrate different ExpectedConditions. Let’s have a look at these one by one.
Test Scenario 1:
- Initialize WebDriverWait with a timeout of 10 seconds.
- Navigate to the LambdaTest eCommerce Playground website.
- Use presenceOfElementLocated to locate a dynamic loading image.
- Use elementToBeClickable to wait for the element to be clickable and click on it.
- Use visibilityOfElementLocated to locate an element on the new page after clicking.
- Use visibilityOfAllElementsLocatedBy to locate all the elements on the newly loaded webpage and assert the size.
Test Implementation:
This test script uses explicit waits with WebDriverWait in Selenium Java. It interacts with a LambdaTest eCommerce website and performs a different set of actions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@Test(description="WebDriverWait demonstration 1") public void testExplicitWait_1() { // Initialize WebDriverWait with a timeout of 10 seconds WebDriverWait wait =new WebDriverWait(driver, Duration.ofSeconds(10)); // LambdaTest e-commerce website to check for dynamic loading elements driver.get("https://ecommerce-playground.lambdatest.io/"); try { // ExpectedCondition to wait for element to be present : presenceOfElementLocated WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("entry_217966"))); // ExpectedCondition to check if element is clickable and then click on it: elementToBeClickable element = wait.until(ExpectedConditions.elementToBeClickable(By.id("entry_217966"))); element.click(); // ExpectedCondition to wait for element to be visible after the click: visibilityOfElementLocated element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@title='iPod Touch']"))); // ExpectedCondition to wait for all input type elements : visibilityOfAllElementsLocatedBy // assert if the expected length of elements located is 15 List<WebElement> elements = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//*[@class='carousel-item active']"))); Assert.assertEquals(elements.size(), 15); status = "passed"; } catch (TimeoutException ex) { ex.printStackTrace(); } } |
Code Walkthrough:
Start by initializing a WebDriverWait object, which will be used in the test case flow to implement ExpectedConditions as required. This will be a common step in all cases.
The maximum wait time for this is 10 seconds, which means the driver waits for a maximum of 10 seconds for the condition to be fulfilled before throwing an exception.
Navigate to the LambdaTest eCommerce Playground website. Start the try block for better exception handling and implement the ExpectedCondition to wait for the dynamic loading image WebElement to be present using the presenceOfElementLocated() method. Then, implement the ExpectedCondition to wait for the same element to be clickable after its presence is confirmed using the elementToBeClickable() method and then click on it.
After clicking the same, wait for an element to be visible on the newly loaded page after redirection. For this, we have used the visibilityOfElementLocated() method to wait for the image to be visible before proceeding. Next, we use the visibilityOfAllElementsLocatedBy() method to check if all the product images are loaded on the page. For this, we assert the size to verify it.
Finally, update the status as passed for better visibility on the LambdaTest Web Automation dashboard and add a catch block for graceful exception handling in case there is any exception.
Test Scenario 2:
- Initialize WebDriverWait with a timeout of 10 seconds.
- Navigate to the Simple iframe page of the LambdaTest Selenium Playground website.
- Use titleContains and verify the page title.
- Use textToBe and check if the iFrame section is present.
- Use frameToBeAvailableAndSwitchToIt to locate the frame and switch to it.
- Use textToBePresentInElementLocated to locate an element in iFrame to verify the switch.
Test Implementation:
This test script uses explicit waits using WebDriverWait in Selenium Java for handling dynamic content on a Simple iframe page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@Test(description="WebDriverWait demonstration 2") public void testExplicitWait_2() { // Initialize WebDriverWait with a timeout of 10 seconds WebDriverWait wait =new WebDriverWait(driver, Duration.ofSeconds(10)); // Navigate to iframe demo page driver.get("https://www.lambdatest.com/selenium-playground/iframe-demo/"); try { // ExpectedCondition to wait for title to contain given text: titleContains wait.until(ExpectedConditions.titleContains("Selenium Playground")); System.out.println("Page title is : " + driver.getTitle()); // ExpectedCondition to wait for element using the text : textToBe wait.until(ExpectedConditions.textToBe(By.xpath("//*[contains(text(),'containing webpage')]"), "Simple iFrame containing webpage")); // ExpectedCondition to wait for iFrame and switch to it : frameToBeAvailableAndSwitchToIt driver = (RemoteWebDriver) wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("iFrame2"))); // Verify switch to iframe is successful using expected condition by comparing text // ExpectedCondition to wait/verify for presence of element by text : textToBePresentInElementLocated Boolean iFrame = wait.until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//*[contains(@href,'api-doc')]"), "API")); System.out.println("Switched to iframe : " + iFrame); status = "passed"; } catch (TimeoutException ex) { ex.printStackTrace(); } } |
Code Walkthrough:
Create and initialize the WebDriverWait object with a max wait time of 10 seconds and then navigate to the Simple iframe demo website. Now, wait for the title of the page to contain Selenium Playground words using the titleContains() method before logging the title.
Next, we check if the required iFrame is present or not using the textToBe() method for its header. Switch to the iFrame once it is available using the frameToBeAvailableAndSwitchToIt() method and store its reference in the RemoteWebDriver object by casting the WebDriver object to it. After that, check for an element inside the iFrame using the textToBePresentInElementLocated() method to verify that the switch to iFrame was successful.
Test Scenario 3:
- Initialize WebDriverWait with a timeout of 10 seconds.
- Navigate to the Javascript Alert Box Demo page of the LambdaTest Selenium Playground website.
- Click on the button to get an alert.
- Use alertIsPresent to wait for the alert.
- Switch to alert and get the alert text.
Test Implementation:
This test script uses explicit waits using WebDriverWait in Selenium Java for handling JavaScript alerts on a Javascript Alert Box Demo page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@Test(description="WebDriverWait demonstration 3") public void testExplicitWait_3() { // Initialize WebDriverWait with a timeout of 10 seconds WebDriverWait wait =new WebDriverWait(driver, Duration.ofSeconds(10)); // Navigate to iframe demo page driver.get("https://www.lambdatest.com/selenium-playground/javascript-alert-box-demo"); try { // Click on the button to get alert driver.findElement(By.xpath("(//*[@type='button'])[1]")).click(); // ExpectedCondition to wait for alert : alertIsPresent wait.until(ExpectedConditions.alertIsPresent()); System.out.println("Alert text is : " + driver.switchTo().alert().getText()); status = "passed"; } catch (TimeoutException ex) { ex.printStackTrace(); } } |
Code Walkthrough:
Create and initialize the WebDriverWait object with a max wait time of 10 seconds and then navigate to the Javascript Alert Box Demo page. Now, click on the button to get an alert.
Next, use the alertIsPresent() method to wait for the alert. Once the condition is fulfilled, switch to the alert to get the alert text.
Then, update the test case status and add a catch block to handle the exception in case ExpectedCondition fails to find the alert in the given 10 seconds.
Test Scenario 4:
- Initialize WebDriverWait with a timeout of 10 seconds.
- Navigate to the Checkbox Demo page of the LambdaTest Selenium Playground website.
- Check the checkbox to get a message.
- Use elementToBeSelected to confirm the checkbox is checked.
- Uncheck the checkbox to hide the message.
- Use invisibilityOf to confirm that the message is hidden.
Test Implementation:
This test script uses explicit waits using WebDriverWait in Selenium Java for handling checkbox interactions on a Checkbox Demo page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@Test(description="WebDriverWait demonstration 4") public void testExplicitWait_4() { // Initialize WebDriverWait with a timeout of 10 seconds WebDriverWait wait =new WebDriverWait(driver, Duration.ofSeconds(10)); // Navigate to iframe demo page driver.get("https://www.lambdatest.com/selenium-playground/checkbox-demo"); try { // check the checkbox to display message driver.findElement(By.id("isAgeSelected")).click(); // ExpectedCondition to wait for checkbox to be selected: elementToBeSelected wait.until(ExpectedConditions.elementToBeSelected(By.id("isAgeSelected"))); // uncheck the checkbox to hide the message driver.findElement(By.id("isAgeSelected")).click(); // ExpectedCondition to wait for element to be invisible : invisibilityOf // Verify that the message is invisible now. Boolean isInvisible = wait.until(ExpectedConditions.invisibilityOf(driver.findElement(By.id("txtAge")))); System.out.println("Message is invisible : " + isInvisible); status = "passed"; } catch (TimeoutException ex) { ex.printStackTrace(); } } |
Code Walkthrough:
Create and initialize the WebDriverWait object with a max wait time of 10 seconds, and then navigate to the Checkbox Demo page. Now, check the checkbox and then use the elementToBeSelected() method to ensure that the checkbox is selected.
Then, uncheck the checkbox and use the invisibilityOf() method to wait and verify that the message displayed earlier is no longer visible after the checkbox is unchecked.
Running Tests
To view the execution results, navigate to the LambdaTest Web Automation dashboard.
Best Practices for Using Selenium WebDriverWait
A few best practices using which we can make the best use of WebDriverWait in our Selenium automation script are as follows:
- Analyze the Behavior: It is the first and foremost step before starting to implement waits. Analyzing the website thoroughly helps you to understand if waits are required are not. If required, which type of wait and with what timeout should you use to have properly balanced wait times to prevent any longer executions and flaky tests.
- Use Appropriate Wait and Timeouts: You need to set timeouts based on the expected behavior of the website. Avoid excessively long timeouts as they can slow down your tests and unnecessarily increase the execution time, giving false results.
- Combine Multiple Conditions: You can also combine multiple expected conditions using logical operators to create complex waiting scenarios for slow-loading dynamic elements. This is mostly used in cases where various conditions must be valid before proceeding further.
- Use Fluent Wait for Customizations: For newer versions of many dynamic customer-friendly websites, different elements might get loaded on different actions with different load times. In such cases, a more effective wait strategy is required. This can be achieved using fluent waits, as it gives more control over the waits in the automation scripts by supporting custom polling and exception handling.
- Handle TimeoutException: Always have your wait commands wrapped in a try-catch block to gracefully handle TimeoutException or any other exception that might occur. This helps to gather required error logs or perform any necessary actions in case of an exception.
Implicit waits should always be a reasonable time, not too short and not too long and explicit waits only in conditions where more precise and granular control is required over any WebElement before interacting.
Subscribe to the LambdaTest YouTube Channel and stay updated with more such tutorials.
Conclusion
With this, we came to an end to this blog on WebDriverWait in Selenium Java, where we learned about different wait types and methods that can be used as per the requirement to make test scripts robust and reliable. We also saw how using WebDriverWait in Selenium Java helps in synchronizing test execution for the dynamic behavior of web pages.
By understanding and applying these different waits with the help of ExpectedConditions, you can handle various waiting scenarios effectively in your automation scripts and make the test results more precise and efficient.
You can also use WebDriverWait in Selenium with various programming languages such as C#. To know more, refer to this blog on WebDriverWait in Selenium C#.
Frequently Asked Questions (FAQs)
What is a WebDriverWait in Selenium?
WebDriverWait is a Selenium class used to wait for specific conditions (like element visibility or page load) before proceeding with further actions, ensuring dynamic web elements are handled properly.
Is WebDriverWait a class or interface?
WebDriverWait is a class in Selenium that extends the FluentWait class, providing mechanisms for waiting until a certain condition is met.
How to use driver wait in Java?
In Java, WebDriverWait is used by creating an instance with a timeout and then applying it to a condition using the until method to wait for elements or events.
How to create a WebDriverWait instance for 30 seconds?
Here is the below line of code to create a WebDriverWait instance for 30 seconds:
1 |
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); |
Got Questions? Drop them on LambdaTest Community. Visit now