RyanSchlomer.com

Sr QA Consultant

Why You Shouldn’t Use Sleeps in Your Automation Tests and How to Get Rid of Them

Posted by:

|

On:

|

,

In the world of automation testing, time is of the essence. While it may be tempting to use Thread.Sleep() to pause the execution of your test for a specific amount of time, this approach is generally considered a bad practice. In this blog post, I’ll explore why using sleeps in your automation tests is problematic and how you can replace them with more efficient and reliable alternatives.

The Problem with Sleeps

1. Inefficiency

Using Thread.Sleep() to pause the test execution for a fixed period is inefficient. You’re essentially blocking the test for a set amount of time, even if the condition you’re waiting for is met before the sleep duration ends.

2. Flakiness

Sleeps introduce flakiness into your tests. If you set the sleep time too short, the test may fail because the condition isn’t met in time. If you set it too long, you’re wasting valuable time that could be used for running more tests.

3. Lack of Flexibility

The sleep time is a hardcoded value, making it inflexible. If the application under test changes its behavior or performance, you’ll have to manually update all the sleep times in your tests.

4. Poor Scalability

As your test suite grows, the total time wasted on sleeps can become significant, making your automation pipeline slower and less scalable.

Better Alternatives

1. Explicit Waits

Instead of using sleeps, you can use explicit waits to pause the test until a certain condition is met. For example, in Selenium with C#, you can use WebDriverWait along with SeleniumExtras.WaitHelpers.ExpectedConditions to wait for an element to be clickable or visible.

Here’s some sample code:

        public static IWebElement WaitForElementToBeClickable(this IWebDriver driver, By by, int timeOut = 10)
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut));
            return wait.Until(ExpectedConditions.ElementToBeClickable(by));
        }
        
        public static IWebElement WaitForElementToBeVisible(this IWebDriver driver, By by, int timeOut = 10)
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut));
            return wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(by));
        }

2. Retry Logic

If you’re already using retry logic, that’s a step in the right direction. However, instead of using Thread.Sleep() in your retry loop, consider using a more dynamic waiting mechanism.

Here’s how you can implement retry logic without sleeps:

public static IWebElement WaitForElementWithRetry(this IWebDriver driver, By by, int maxRetries = 3, int timeOut = 10)
{
    for (int i = 0; i < maxRetries; i++)
    {
        try
        {
            return WaitForElementToBeClickable(driver, by, timeOut);
        }
        catch (WebDriverTimeoutException)
        {
            if (i == maxRetries - 1)
            {
                throw;
            }
        }
    }
    return null;
}

3. Wait for Page to Load

You can also wait for the entire page to load using JavaScript’s document.readyState property.

public static bool WaitForPageToLoad(this IWebDriver driver, int timeOut = 10)
{
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut));
    return wait.Until(_driver => ((IJavaScriptExecutor)_driver).ExecuteScript("return document.readyState").Equals("complete"));
}

Conclusion

Using sleeps in your automation tests is a practice best avoided. It makes your tests inefficient, flaky, and hard to maintain. Instead, leverage the power of explicit waits and dynamic retry mechanisms to make your tests more robust and efficient.