Steve Wortham
Posted on October 9, 2024
In today’s world of automation testing, timing is everything. Imagine running a test script that goes through a web application, just to have it fail because the page didn’t load fast enough or an element wasn’t visible right at that moment when the script tried to work with it. This could be because of several reasons like network speed, server response time, and client-side rendering. These are the types of timing issues that can make automated tests unreliable and frustrating for maintenance and a complete waste of time. This is where the concept of “waits” in automation testing becomes crucial.
To resolve these time issues, Selenium WebDriver, one of the most widely used tools in web automation, provides support for various types of waits. These waits commands ensure that your test script waits until certain conditions are met-for instance, an element is present in the DOM, or a page load is completed. Understanding and effectively using these waits is key to designing robust and stable automated tests, especially for handling dynamic content or unpredictable loading times.
In this blog, we will explain three types of waits available in Selenium: implicit, explicit, and fluent wait. We will explain precisely how each of them works, what problem each can solve, and the best practices for their implementation within your test automation framework. Whether you are an experienced tester or just starting out, once mastered, these waits will take your test scripts to a whole new level in terms of stability and efficiency.
What is Selenium Wait?
Selenium Wait is a mechanism in Selenium WebDriver that makes it wait until certain conditions are met before executing further commands of the test script. These typically contain a wait for one of the web page elements to either be loaded or interactable. Without waits, test scripts will fail in trying to perform activities with elements that have not appeared yet, or their loading is not complete; this makes tests unreliable and inconsistent.
The waits in Selenium ensure that your test script will wait (instead of pausing it with thread.sleep()) until the condition you name is satisfied-for instance, the presence of an element in the DOM or completing a page load. The concept and usage of these waits are pretty important in correctly designing automated tests of good quality.
Types of Selenium Wait Commands
Selenium provides three different types of wait commands that efficiently handle various timing scenarios and enhance the reliability of automated tests as follows:
- Implicit Wait: It sets a default time for WebDriver to wait for an element to appear before throwing an exception, applying to all elements by default. It’s used as a global wait for all elements in your test script and does not wait for specific conditions. Once set, it remains accessible and active throughout the session of the driver.
- Explicit Wait: This wait is more targeted oriented, you can set it for what condition you want to continue with the execution. In explicit waits, you can set on an element or on conditions, for instance, till an element is visible or it’s clickable.
- Fluent Wait: This is an advanced version of the explicit wait. Fluent Wait enables you to define the maximum amount of time to wait for a condition, as well as the frequency with which the WebDriver checks whether the condition is met. It also allows ignoring specific exceptions while waiting, such as NoSuchElementException. Selenium waits are the best way to ensure your test scripts will interact with web elements only when those are ready for interaction, hence making the automation of tests much more stable and reliable.
Implicit Wait In Selenium
Implicit Wait is one of the simple yet very useful features available in Selenium, which will instruct the WebDriver to wait for a certain period of time before throwing a no such element exception (NoSuchElementException) if it cannot find an element on the page. Once set, it applies globally to all element searches performed by WebDriver for the duration of that WebDriver instance.
How It Works
Whenever there is a defined implicit wait, it will automatically wait for the defined time every time it attempts to locate an element. If it shows up before the time, then it goes ahead with the script without delay. In case it doesn’t show up within this given time, Selenium stops the script and throws an exception indicating that the element was not found.
Syntax to Implicit Wait in Selenium
Here’s how you can implement Implicit Wait in Selenium:
// Setting the implicit wait for 10 seconds
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
In this Selenium Java example, the WebDriver will wait up to 10 seconds for any element to appear before moving on to the next step in the script.
When to Use Implicit Wait
Implicit Wait is extremely useful in cases where you are testing a pretty simple web application because most of the elements load within a predictable time range. While it can help minimize failed test scripts due to small loading delays, over-reliance on Implicit Wait may lead to longer test execution times if used improperly.
However, it is critical to notice that since the setting of Implicit Wait is global, in complex cases where different elements may require different wait times, it may not be perfect. In such cases, Explicit Wait or Fluent Wait, which offer greater control over specific conditions and timeouts, are more appropriate.
Explicit Wait In Selenium
Explicit Wait is an advanced and flexible way of applying a waiting mechanism, using which a user can define the specific conditions for the WebDriver to wait, unlike Implicit Waits, which apply a timeout globally to all elements. Explicit Waits provide the flexibility to specify the wait conditions on certain elements or the occurrence of specific conditions that enhance its usability.
How It Works
Explicit wait works by combining a nominated maximum wait time with one or more expected conditions. The WebDriver will check the condition at regular intervals, typically every 500 milliseconds by default, during that time. If the condition is met within the timeout, the WebDriver continues with the next step; otherwise, it raises a TimeoutException.
Syntax to Explicit Wait in Selenium
To implement Explicit Wait in Selenium, you use the WebDriverWait class along with ExpectedConditions. Here’s the basic syntax:
// Import the necessary packages
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.By;
// Create a WebDriverWait instance
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// Use Explicit Wait to wait for a specific condition
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("element_id")));
In this example, the WebDriver waits up to 10 seconds for the element with the Selenium locator (id=”element_id”) to become visible. If the element is visible before 10 seconds, the script continues; if not, an exception is thrown.
When to Use Explicit Wait
Explicit Wait is ideal for scenarios where fine-grained control over waiting on a particular element or condition is necessary, and you can even adjust the polling interval for checking conditions. In particular, it is very useful when:
- Dynamic Content: Pages which load elements dynamically, usually driven by technologies like AJAX.
- Specialized Conditions: When you have to wait for specific states of elements, for instance, visibility, clickability, and text presence.
- Unpredictable Load Times: In applications where the load times of elements can’t be predicted or vary a lot.
Types of Expected Conditions in Explicit Wait
Explicit waits allow for waiting until certain conditions are met before the test script is executed, or throwing exceptions when they cannot be satisfied. This is facilitated with the help of Selenium’s ExpectedCondition class. Many conditions can be used with waits as follows:
- Visibility of Element: Waits until an element is visible using ExpectedConditions.visibilityOf(element).
- Element Clickable: Waits until an element is visible and enabled with ExpectedConditions.elementToBeClickable(element).
- Presence of Element: Waits until an element is present in the DOM using ExpectedConditions.presenceOfElementLocated(by).
- Text in Element: Waits until specific text appears in an element with ExpectedConditions.textToBePresentInElement(element, text).
- Alert is Present: Waits until an alert is displayed using ExpectedConditions.alertIsPresent().
- Element Selection State: Waits until an element’s selection state matches the condition with ExpectedConditions.elementToBeSelected(element).
- Frame Available: Waits until a frame is available, then switches to it using ExpectedConditions.frameToBeAvailableAndSwitchToIt(by).
- Element Invisibility: Waits until an element is no longer visible with ExpectedConditions.invisibilityOf(element).
- URL Contains: Waits until the URL contains a specific substring using ExpectedConditions.urlContains(substring).
- Title is: Waits until the page title matches a specific value with ExpectedConditions.titleIs(title).
Fluent Wait In Selenium
Fluent Wait is an advanced version of explicit wait offering more flexibility in dealing with dynamic web elements. Unlike the standard explicit wait, Fluent Wait allows you to specify:
- Polling Frequency: How often should the condition be checked? For example, every 500 milliseconds.
- Timeout: Maximum time to wait for the condition to be met.
- Ignoring Exceptions: You can configure Fluent Wait to ignore specific exceptions, like NoSuchElementException, and continue checking the condition without failing immediately.
How It Works
Fluent Wait will continuously poll the DOM until the condition is met or the timeout expires. In case the condition is met, it then proceeds with the execution of the script; if not, it throws an exception.
Syntax for Fluent Wait in Selenium
Here’s the basic syntax for Fluent Wait in Selenium:
Wait wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30)) // Maximum time to wait
.pollingEvery(Duration.ofMillis(500)) // Interval between each poll
.ignoring(NoSuchElementException.class); // Exceptions to ignore
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementID")));
- withTimeout(Duration.ofSeconds(30)): This sets the maximum amount of time Selenium will wait for the condition to be met (in this case, 30 seconds).
- pollingEvery(Duration.ofMillis(500)): This defines the polling interval, meaning Selenium will check the condition every 500 milliseconds.
- ignoring(NoSuchElementException.class): This tells Selenium to ignore NoSuchElementException during the wait period, allowing it to continue polling instead of throwing an exception immediately.
When to Use
Fluent Wait proves pretty useful when used with best Selenium practices in the following cases:
- Dynamic Loading of Content: In cases when elements loaded dynamically on the page may not pop up at once after an action has been performed. Such examples include waiting for a loading spinner to disappear or content becoming visible post performing an AJAX call.
- Unpredictable Delays: Fluent Wait allows you to handle such cases when there are unpredictable delays in the appearance of an element or a change in its state, through polling frequency and timeout.
- Custom Waiting Logic: Fluent Wait can be used to wait for an element to change color or for a specific value in an element’s attribute. This makes it ideal for waiting for custom conditions. Fluent Wait can be customized to wait for any condition to be checked by a function; hence, it is ideal for complicated scenarios.
Difference Between Selenium Wait and Thread.sleep()
Thread.sleep() is a Java method that pauses the test script’s execution for a specified period of time, measured in milliseconds. By using this, testers can achieve the wait required to have reliable test automation scripts. However, it is very different from the Selenium wait in terms of usability and working. Let’s understand the common difference between the two in different scenarios.
Dynamic vs. Static Waiting
- Selenium Wait: Selenium Wait introduces dynamic waiting by waiting until the specified condition is met, up to a maximum timeout. If the condition is met earlier, the test proceeds without further delay, improving efficiency. The efficiency of the test will be better.
- Thread.sleep(): It uses a static waiting where it makes the test wait for a fixed amount of time without actually telling it whether the condition is met, which will lead to inefficient test execution.
Conditional Logic vs. Blind Waiting
- Selenium Wait: It will actually wait actively for some conditions such as visibility or clickability of an element and move further. The conditional logic prevents unnecessary delays.
- Thread.sleep(): The absence of any conditional logic makes it sleep for the time it is set for, which may be too much or too little and affects test accuracy.
Efficiency and Test Speed
- Selenium Wait: Enhances test performance by avoiding unnecessary wait time. As the test would continue right away when the condition is met, this improves overall performance.
- Thread.sleep(): This can hang the tests quite significantly. It waits for its hard-wired time, which is totally unnecessary in many instances. This could lead to a longer time in test execution.
Error Handling and Robustness
- Selenium Wait: It is more robust because it allows the handling of exceptions like NoSuchElementException, improving test stability and reducing test flakiness.
- Thread.sleep(): Does not have error handling during the waiting time, hence tests may break if something is not loaded on time; tests tend to be more fragile.
Use Cases
- Selenium Wait: It is best used for handling asynchronous events, dynamic content, and when the timing of element availability is not certain.
- Thread.sleep(): This should only be used rarely when a fixed delay is needed, such as in debugging or communicating with systems out of the control of the browser.
Conclusion
Effective managing wait time is a very important aspect of test automation, and fortunately, Selenium has a very solid set of waiting mechanisms to deal with complexities brought in by dynamic web content, API calls, client side rendering, etc. From Implicit Wait and Explicit Wait to Fluent Wait, testers can solve a wide variety of timing problems with precision and flexibility. It ensures adaptability against constantly changing conditions for efficiency, yet resilient tests in their nature for modern web applications.
Source: This article was originally published at testgrid.io.
Posted on October 9, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.