Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing with Thread.sleep

What are the recommended approaches to using Thread.sleep() to speed up tests.

I am testing a network library with a retry functionality when connections are dropped or timeout errors occur, etc. The library however, uses a Thread.sleep() between the retries (so it won't connect thousands times while the server is restarting). The call is slowing the unit tests significantly, and I wonder what the options are to override it.

Note, I'm open to actually changing the code, or using a mocking framework to mock Thread.sleep(), but would like to hear your opinions/recommendation first.

like image 751
notnoop Avatar asked Dec 08 '09 17:12

notnoop


People also ask

Is it a good practice to use thread sleep?

Using Thread. sleep() frequently in an automation framework is not a good practice. If the applied sleep is of 5 secs and the web element is displayed in 2 secs only, the extra 3 secs will increase the execution time.

Why we should not use thread sleep in selenium?

sleep() in Selenium Java because it is a static wait. Selenium WebDriver will have no choice but to wait for the specified time, regardless of the fact that the element has been located or not. This is why we prefer not to use Thread. sleep() multiple times in our automation scripts.

What happens when a sleep is called on thread?

sleep() functions to execute, it always pauses the current thread execution. If any other thread interrupts when the thread is sleeping, then InterruptedException will be thrown.


2 Answers

It is usually a good idea to delegate time-related functionality to a separate component. That include getting the current time, as well as delays like Thread.sleep(). This way it is easy to substitute this component with mock during testing, as well as switch to a different implementation.

like image 69
Eugene Kuleshov Avatar answered Sep 20 '22 20:09

Eugene Kuleshov


I just faced a similar issue and I created a Sleeper interface to abstract this away:

public interface Sleeper
{
    void sleep( long millis ) throws InterruptedException;
}

The default implementation uses Thread.sleep():

public class ThreadSleeper implements Sleeper
{
    @Override
    public void sleep( long millis ) throws InterruptedException
    {
        Thread.sleep( millis );
    }
}

In my unit tests, I inject a FixedDateTimeAdvanceSleeper:

public class FixedDateTimeAdvanceSleeper implements Sleeper
{
    @Override
    public void sleep( long millis ) throws InterruptedException
    {
        DateTimeUtils.setCurrentMillisFixed( DateTime.now().getMillis() + millis );
    }
}

This allows me to query the time in a unit test:

assertThat( new DateTime( DateTimeUtils.currentTimeMillis() ) ).isEqualTo( new DateTime( "2014-03-27T00:00:30" ) );

Note that you need to fix the time first using DateTimeUtils.setCurrentMillisFixed( new DateTime( "2014-03-26T09:37:13" ).getMillis() ); at the start of your test and restore the time again after the test using DateTimeUtils.setCurrentMillisSystem();

like image 37
Wim Deblauwe Avatar answered Sep 19 '22 20:09

Wim Deblauwe