How to Use Thread.sleep() in Selenium
Faisal Khatri
Posted On: April 25, 2024
206408 Views
20 Min Read
When performing Selenium automation testing, you might encounter a NoSuchElementException() when the element you’re trying to interact with isn’t found.
This error typically occurs due to the element existing on the page but takes a considerable amount of time to load and become visible to the user. During test automation, this delay may cause significant issues and halt the execution of test scripts. This is where the Thread.sleep() in Selenium can be helpful in such cases.
In this blog, we look at how to use Thread.sleep() in Selenium using Java.
- What Are Wait Commands in Selenium?
- What Is Thread.sleep() in Selenium?
- Why Use Thread.sleep() in Selenium?
- Difference Between Selenium Waits and Thread.sleep()
- Demo: Using Thread.sleep() in Selenium for Test Automation
- How to Avoid Multiple Thread.sleep() in Selenium?
- Element Is Found Using Thread.sleep() but Not Implicit/Explicit Waits
- Limitations of Using Thread.sleep() in Selenium
- Alternatives to Thread.sleep() in Selenium
- LambdaTest SmartWait for Selenium Test Automation
- Frequently Asked Questions (FAQs)
What Are Wait Commands in Selenium?
Before we discuss the Thread.sleep() method, let’s understand the wait command in Selenium and the different types of waits in Selenium.
Selenium wait commands are placed in the test scripts to tell automation to hold on for a certain amount of time or until a specific condition is met before proceeding with the next step. This prevents errors from occurring if elements on the web page aren’t fully loaded or interactive yet.
Here are the different types of wait commands in Selenium:
- Implicit Waits: These waits are used to search for a WebElement if it needs some time to load and is not immediately available. The implicit waits are globally applied to all the WebElements on the web page and remain in the WebDriver object. It is non-blocking and does not wait for the entire duration, like Thread.sleep().
- Explicit Waits: These waits are used to wait for a specified time until the expected condition is met. This expected condition can be set using the class ExpectedConditions in Selenium. Explicit waits can be applied to a specific WebElement and do not affect the other WebElements on the web page. It will throw the TimeOutException if the WebElement is not found within the specified time.
- Fluent Waits: These waits are more advanced and flexible than implicit and explicit waits. They allow the user to define a custom condition and the polling interval. It also provides an option to ignore the specified exceptions during the time duration while waiting for the WebElement. This helps in waiting for the WebElements that may change over time.
If the WebElement is not found during the specified time, it will throw the NoSuchElementException().
Example:
1 |
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); |
Example:
1 2 3 |
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5)); WebElement checkoutBtn = driver().findElement(By.cssSelector("#check")); wait.until(ExpectedConditions.visibilityOf(checkoutBtn)); |
In the example code above, the checkout button is located using the explicit wait. The WebDriverWait class is instantiated in which the WebDriver instance and the time duration are provided. Using the ExpectedConditions class, the condition is set to wait until the checkout button is visible.
Example:
1 2 3 4 5 6 7 8 |
public String successMessageText() { Wait<WebDriver> wait = new FluentWait<>(driver) .withTimeout(Duration.ofSeconds(10)) .pollingEvery(Duration.ofSeconds(2)) .ignoring(NoSuchElementException.class); WebElement successMessage = wait.until(driver -> notificationPopUp().findElement(By.tagName("p"))); return successMessage.getText(); |
In the above code example, the successMessageText() method returns a text from a WebElement using fluent wait. The Wait interface is used to instantiate the fluent wait of 10 seconds that will be polling at a frequency of every 2 seconds, ignoring NoSuchElementException(). Finally, it will return the text in String format.
What Is Thread.sleep() in Selenium?
To make the automated test scripts less flaky, there is a need to add waits, which will add some waiting time for an element or all the elements in the web page to load. Implementing these waits depends on the type of wait in the automation script.
The two most commonly used Selenium waits are implicit and explicit. However, there are a few instances where Thread.sleep() in Selenium would be considered a better choice.
Thread.sleep() is a static Java method that suspends the code for a specific time. It pauses the execution and helps us to know what has happened during the pause. It accepts the time specified in milliseconds. This function is particularly helpful for debugging a website or web page. To learn more about it, go through this blog on the Thread.sleep() method in Java.
Syntax for Thread.sleep() in Selenium:
1 2 |
//Pauses test execution for specified time in milliseconds Thread.sleep(1000); |
While using this method, you may face a common exception – InterruptedException, which has to be handled either by using throws or try-catch block as shown below:
1 2 3 4 5 6 7 8 9 |
try{ Thread.sleep(1000); } catch(InterruptedException ie){ } Or public static void main(String args[]) throws InterruptedException{ Thread.sleep(1000); } |
In the next sections, we will understand why and how to use Thread.sleep() in Selenium. However, let’s take a look at why the Thread.sleep() method is used for Selenium automation.
Why Use Thread.sleep() in Selenium?
As web applications continue to grow in complexity, their loading times vary greatly. Thread.sleep() method becomes essential in accounting for these varying load times within our Selenium scripts. Using Thread.sleep() in Selenium ensures smooth execution of automated tests, preventing script failures.
Here are some key reasons why Thread.sleep() method is used in Selenium:
- Handle Dynamic Elements: There might be times where the web page has dynamic elements, and it will be hard to predict the behavior. For example, most eCommerce websites have a carousel/slider design that changes dynamically. Instead of using Selenium waits to check for the visibility of the web element, we can choose the Thread.sleep() method to wait for a few seconds.
- Debugging: Thread.sleep() method helps debug the web automation test failures. For example, the tests failing due to NoSuchElementException() can be debugged by adding a Thread.sleep() method, allowing the code to wait for 2 to 5 seconds.
- Testing Third-Party Components: When testing web pages that interact with third-party components, it is important to understand how they were designed instead of knowing how long it takes for a WebElement to be visible on the web page. Hence, predicting the conditions to handle the WebElements seems complex and sometimes even impossible. In such situations, we can delay the execution time using the Thread.sleep() method.
- Handle AJAX Calls: Asynchronous JavaScript and XML (AJAX) are advanced communication techniques that allow the web page to request specific information from the server without affecting the current state of the web page.
The Thread.sleep() method will be one of the best choices to handle the AJAX calls on the web page, as the test would wait a certain period for the server to respond.
This will help in better visibility of the failure to know if the test fails as the element could not be loaded during the code execution. After adding the Thread.sleep() method, if the test passes, then it should be noted that we can add explicit or fluent waits in the test to wait for the WebElement to be loaded before the test moves to the next line to interact with the WebElement.
Difference Between Selenium Waits and Thread.sleep()
In this section, we will dig deeper into the difference between Selenium waits and the Thread.sleep() method.
Aspect | Selenium Waits (Implicit, Explicit, Fluent) | Thread.sleep() |
---|---|---|
Belongs to | Selenium framework. | Thread class of Java. |
Execution Suspension | Waits until a specified condition is met or a timeout occurs. | Ceases execution thread for a specified time. |
Script Execution | Moves to the next line if the element is found before the specified time. | Pauses script execution, regardless of element presence. |
Applicability | Applies globally, it needs to be written once for the entire WebDriver instance. | Needs to be written for each web element. |
Impact on Script Execution Time | Helps reduce script execution time. | Increases script execution time. |
Preferred Option in Selenium Java | Preferred due to efficient handling of element wait conditions. | Less preferred due to its blocking nature. |
Demo: Using Thread.sleep() in Selenium for Test Automation
In this section, let’s dive into the demonstration and check how to implement the Thread.sleep() in Selenium Java.
To showcase its implementation, we will use an example of the LambdaTest eCommerce Playground website. The tests will be executed on a cloud-based testing platform like LambdaTest using Chrome browser on Windows 10.
LambdaTest is an AI-powered test orchestration and execution platform that lets you perform automation testing at scale on a remote test lab that offers 3000+ real environments. The platform also provides Java automation testing using the Selenium WebDriver.
Test Scenario:
|
Test Implementation:
Let’s first create a new Java class file named ThreadSleepDemoTests.java. This class will have all implementations of the test scenario and also the configuration required for running the tests on the LambdaTest Cloud Grid.
1 2 3 4 5 6 |
public class ThreadSleepDemoTests { private WebDriver driver; // … } |
The setup() method is created inside the ThreadSleepDemoTests class, which has the configuration details to run the test on the LambdaTest online Selenium Grid.
1 2 3 4 5 6 7 8 9 10 11 |
@BeforeTest public void setup() { final String userName = System.getenv("LT_USERNAME") == null ? "LT_USERNAME" : System.getenv("LT_USERNAME"); final String accessKey = System.getenv("LT_ACCESS_KEY") == null ? "LT_ACCESS_KEY" : System.getenv("LT_ACCESS_KEY"); final String gridUrl = "@hub.lambdatest.com/wd/hub"; try { this.driver = new RemoteWebDriver(new URL("http://" + userName + ":" + accessKey + gridUrl), getChromeOptions()); } catch (final MalformedURLException e) { System.out.println("Could not start the remote session on LambdaTest cloud grid"); } } |
LambdaTest Username and Access Key values are mandatory values without which the tests can not be run on the LambdaTest cloud platform. As these are confidential values, they should not be hardcoded in the code. We will pass these values using environment variables.
Some more capabilities related to the LambdaTest platform, such as browser name, browser version, test name, build name, etc., need to be passed to run the tests on the LambdaTest Cloud Grid. These capabilities can easily be set using the LambdaTest Automation Capabilities Generator.
The configuration values will be passed by creating a new method getChromeOptions() in the ThreadSleepDemoTests class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public ChromeOptions getChromeOptions() { final var browserOptions = new ChromeOptions(); browserOptions.setPlatformName("Windows 10"); browserOptions.setBrowserVersion("123.0"); final HashMap<String, Object> ltOptions = new HashMap<String, Object>(); ltOptions.put("project", "Thread.sleep Demo on Cloud"); ltOptions.put("build", "LambdaTest e-commerce website test"); ltOptions.put("name", "Thread.sleep demo test"); ltOptions.put("w3c", true); ltOptions.put("plugin", "java-testNG"); browserOptions.setCapability("LT:Options", ltOptions); return browserOptions; } |
As mentioned earlier, we will be running the tests on the Chrome browser on a Windows 10 machine. These respective capabilities are provided in the above method.
The following @Test method will implement the test scenario we discussed earlier for the demo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Test public void testLogin() throws InterruptedException { this.driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=account/login"); final WebElement emailAddress = this.driver.findElement(By.id("input-email")); emailAddress.sendKeys("david.thomson@gmail.com"); final WebElement password = this.driver.findElement(By.id("input-password")); password.sendKeys("Secret@123"); final WebElement loginBtn = this.driver.findElement(By.cssSelector("input.btn-primary")); loginBtn.click(); Thread.sleep(3000); final String myAccountHeaderText = driver.findElement(By.cssSelector("#content h2")).getText(); assertEquals(myAccountHeaderText, "My Account"); } |
The test script will first navigate to the Account Login page of the LambdaTest eCommerce Playground website. It will search for the E-Mail Address field and type in the value david.thomson@gmail.com in it.
Next, the Password field will be located, and the value Secret@123 will be typed in. Finally, it will locate the Login button and click on it.
After the Login button is clicked, the website will navigate to the My Account page, which will take some time to load. Hence, the Thread.sleep() method is used here to wait for 3000 milliseconds before it checks the page header of the My Account page.
Using the Thread.sleep() method here, the My Account page is loaded successfully, and then the assertion is performed.
Test Execution
Following is the screenshot of the test execution performed using IntelliJ IDE:
The test execution details can be found on the LambdaTest Web Automation Dashboard.
You can view the details of test execution for the tests executed on the Chrome 123 version of the Windows 10 platform, which took 10 seconds to run the test.
Details such as logs, video recordings, etc., can be viewed on the Web Automation Dashboard.
How to Avoid Multiple Thread.sleep() in Selenium?
While working with some websites that have slow response time and take time to load, it is observed that testers use multiple Thread.sleep() methods in the test so that WebElements can be loaded successfully on the web page before the code tries to locate the WebElement on the page.
Consider the following code example of LambdaTest eCommerce Playground website where the user navigates to the Home page, waits for it to load before clicking on the Shop by Category menu, and then clicks on the MP3 Players category and again waits for the next page to load.
Here is the test script with multiple Thread.sleep() methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@Test public void testWebsiteNavigation () throws InterruptedException{ this.driver.get("https://ecommerce-playground.lambdatest.io/"); Thread.sleep(1000); this.driver.findElement(By.linkText("Shop by Category")).click(); Thread.sleep(1000); this.driver.findElement(By.cssSelector(".entry-component .entry-widget nav.navbar ul li:nth-child(5) a")).click(); Thread.sleep(1000); } |
Test Execution:
When this code was executed, it took a total of 14 seconds to run. It also took 3000 milliseconds or 3 seconds, considering the Thread.sleep() method has 1 second hard wait after every line of code.
Hence, using multiple Thread.sleep() methods in the tests is not a recommended approach. Instead, explicit waits from Selenium could be used here as it is dynamic in nature and will move to the next line of code once the WebElement is found, saving the time of execution.
Using Explicit Wait Instead of Thread.sleep()
The following code could be used, which uses explicit wait and can perform faster execution as compared to the code using the Thread.sleep() method.
Here is the test script with explicit wait instead of Thread.sleep() method:
1 2 3 4 5 6 7 8 9 10 |
@Test public void testWebsiteNavigationWithExplicitWait() { this.driver.get("https://ecommerce-playground.lambdatest.io/"); final WebDriverWait wait = new WebDriverWait(this.driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Shop by Category"))).click(); wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(".entry-component .entry-widget nav.navbar ul li:nth-child(5) a"))).click(); } |
Test Execution:
When this code was executed, it took a total of 11 seconds to complete the execution. Thus, it saves the 3 seconds that were additionally taken in the previous test execution, which was performed using the Thread.sleep() method. Hence, it is recommended to use Selenium waits in the tests rather than the Thread.sleep() method.
Element Is Found Using Thread.sleep() but Not Implicit/Explicit Waits
You might come across some scenarios where the WebElement could be located using the Thread.sleep() method only. When you try to use the Selenium waits instead of the Thread.sleep() method, the WebElements are not located, resulting in the failure of the tests.
In such cases, it is recommended to debug the test and check out for the actual cause of the error that results in the failure of the tests. Here, the Thread.sleep() method could be used as a debugging mechanism to diagnose the test failure.
For example, an overlay appears on the page when the user tries to click on a button, which results in ElementClickInterceptionException and leads to test failures. Alternate ways should be looked out for to handle the failure instead of directly using the Thread.sleep() method.
Subscribe to the LambdaTest YouTube Channel and stay updated with the latest tutorials around Selenium testing, Jenkins, and more.
There are multiple things that can be checked, like selectors being correct, using appropriate locator strategy, checking if the web page loads correctly, and only the required interaction being performed on the WebElement.
Another alternative is to look out for the root cause of the test failure to know why the implicit or explicit wait is not working to locate the element. For example, locating the overlay page, clicking on it, and then interacting with the desired WebElement on the page.
Similarly, the pause() method can be used from the Actions class in Selenium. The pause() method will pause the execution of the tests for the specified duration.
Limitations of Using Thread.sleep() in Selenium
Even though Thread.sleep() method helps handle dynamic WebElements, debugging, and testing third-party components, it has limitations.
The following are some of the limitations of the Thread.sleep() in Selenium:
- Static Hard Coded Waits: Thread.sleep() method does not adapt the actual state of the application under test. It will halt the test execution for the specified duration of time irrespective if the WebElement is found within the specified time or not. In case of any error or test failures, it will happen after the specified duration of time.
- Unreliable: It is not reliable as it might get interrupted due to other threads or processes and could be affected by factors such as network issues.
- Not Scalable: It increases the overall test execution time, which may result in delayed builds for testing. This may also lead to delays in getting feedback on the builds.
Alternatives to Thread.sleep() in Selenium
The thread.sleep() method has been provided by Java, but when used in automation scripts, it is often considered unstable. Ideally, it is not recommended to use the Thread.sleep() method in test scripts as it may increase the test execution time (as explained in the last section).
Although executing tests with third-party interfaces and AJAX calls might always seem complex, when handled wisely with the proper wait like the Thread.sleep() method, it will ease the execution with high accuracy results.
If that’s not the case with you, you might be better off using other Selenium waits like implicit, explicit, or fluent waits.
SmartWait Functionality by LambdaTest
Cloud-based testing platforms like LambdaTest offer SmartWait functionality for Selenium testing that lets you get rid of the unwanted explicit waits and expected conditions in the code.
It ensures that the actions are performed on the WebElements, which are ready for interaction.
If the actionability checks fail, it throws the relevant Selenium exceptions, which helps quickly identify and resolve the test automation-related issues.
SmartWait helps in writing optimized code that is easy to read and maintain. Once the SmartWait capability is used in the code, there is no need to use explicit, implicit, or fluent waits in the test scripts.
The smartWait capability can be added to the LT:Options capability, which allows the addition of all the capabilities related to the LambdaTest Cloud Grid.
1 2 3 4 5 6 7 |
LT:Options { ... "smartWait": 10 // It accepts integer values as second ... } |
The time in seconds needs to be passed in the smartWait capability. This capability accepts only integers.
We will cover the demonstration of smartWait in the test script in the next section of this blog.
LambdaTest SmartWait for Selenium Test Automation
In the previous section, we learned how to use the Thread.sleep() method in Selenium automation. Multiple Thread.sleep() methods were required to be added in the test scripts to make the execution wait while the screen transition happened. These Thread.sleep() methods helped smooth the execution of the tests, avoiding the flaky tests.
However, as the Thread.sleep() method is a hard wait, the test execution time increased by an additional 3000 milliseconds. This is where the SmartWait feature by LambdaTest can help us reduce the test execution time by eliminating the use of the Thread.sleep() method.
Let’s take the same login scenario of the LambdaTest eCommerce Playground website.
The following smartWait capability will be added in the getChromeOptions() method.
1 2 3 4 5 6 7 |
public ChromeOptions getChromeOptions() { //... ltOptions.put("smartWait", 20); //... } |
The following screenshot shows the implementation of the getChromeOptions() method.
The testLoginWithSmartWait() method performs the same login scenario steps as discussed earlier. However, in this test method, there is no Thread.sleep() method used to wait for the My Account screen to load after the login button is clicked.
LambdaTest SmartWait internally handles all the WebElement readiness for performing actions. This saves the test execution time without writing any extra boilerplate code.
According to the Future of Quality Assurance Survey by LambdaTest, testers spend more than 8% of their time fixing flaky tests. However, the SmartWait functionality enables testers to focus on performing core testing without worrying about test flakiness, saving them valuable time to write efficient test scripts.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Test public void testLoginWithSmartWait() { this.driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=account/login"); final WebElement emailAddress = this.driver.findElement(By.id("input-email")); emailAddress.sendKeys("david.thomson@gmail.com"); final WebElement password = this.driver.findElement(By.id("input-password")); password.sendKeys("Secret@123"); final WebElement loginBtn = this.driver.findElement(By.cssSelector("input.btn-primary")); loginBtn.click(); final String myAccountHeaderText = this.driver.findElement(By.cssSelector("#content h2")).getText(); assertEquals(myAccountHeaderText, "My Account"); } |
Test Execution:
Let’s execute the testLoginWithSmartWait() method and also the previously written test testLogin() that has the Thread.sleep() method implemented that we discussed in the earlier section of this blog, and compare the test execution time taken by both of the tests.
This total time of execution can be verified on the LambdaTest build details screen, as shown in the screenshot below:
It can be observed that the test with the Thread.sleep() method took a total of 8 seconds to run. However, the test with LambdaTest SmartWait took only 6 seconds to run. Thus, saving 2 seconds in the whole test execution.
This is a simple login scenario, so the time difference is much less. However, it can be imagined that in complex scenarios such as end-to-end testing, this execution time can play a vital role.
SmartWait could prove to be a savior for developers and testers. It could save many valuable minutes or hours spent running automated tests, which can help get faster feedback and quality builds without writing any code for explicit, implicit, or fluent waits.
In addition to handling wait times using SmartWait, gaining proficiency in using advanced features can significantly enhance your testing capabilities. Platforms like LambdaTest also offer comprehensive test automation certifications, including Selenium Java 101. This certification validates your expertise and equips you to automate real-life use cases in Selenium Java testing.
Conclusion
Thread.sleep() in Selenium is a kind of hard wait that can be used in Selenium web automated tests.
However, it is not a recommended practice. Instead, we should implement the Selenium waits, which is a more flexible and less time-consuming solution. Thread.sleep() in Selenium is a useful method for web application debugging and can even be implemented with an online Selenium Grid.
Let us know if you have come across any other scenarios where you have found a better way to effectively implement the Thread.sleep() method using Selenium with Java. Also, if you have any questions, feel free to reach out to us via the comment section below.
Frequently Asked Questions (FAQs)
What does sleep do in Selenium?
In Selenium, sleep refers to pausing the test script execution. It’s typically achieved with Thread.sleep() in Java or similar methods in other languages.
How to wait for 30 seconds in Selenium?
The test automation pyramid is a graphical strategy model for automating software testing. The model divides testing types into three layers based on the return on investment (ROI) provided by automating that specific type.
Got Questions? Drop them on LambdaTest Community. Visit now