TLDR; I use Thread.sleep
as a tactic, not a strategy, unless I’m simulating random user pauses, in which case my implementation of that abstraction will involve a sleep.
When do you use Thread.sleep?
I avoid Thread.sleep
as much as possible when automating.
I created an entire LinkedIn Learning course on the topic of Synchronisation to explain as many ways as possible I could for avoiding Thread.sleep
But inevitably there will be occasions where I use Thread.sleep
What are they?
- Use
Thread.sleep
for waiting on the passage of time - temporarily when I can’t identify the correct state based wait yet
- as the pause in a polling mechanism
- tactical solution
The above are the four main ways I seem to allow myself to use Thread.sleep
Why not use Thread.sleep
?
- Do not use
Thread.sleep
just because it is easy.- similarly: Do not use implicit wait, because it is easy and allows you to avoid
Thread.sleep
- similarly: Do not use implicit wait, because it is easy and allows you to avoid
Sometime people use Thread.sleep
because they don’t know how to use any other Synchronisation approach.
I encourage learning how to use WebDriverWait
and other Synchronisation approaches because they will make your automated execution more robust.
Thread.sleep
encourages you to think in terms of the passage of time. But applications rarely work on the basis of the passage of time. Applications work on the basis of ‘state’ and ’events’.
Synchronising ‘with’ the application, rather than in based on the time it sometimes takes for a ‘state’ to be reached or for an ’event’ to fire, will make your automated execution more robust.
Use Thread.sleep
for waiting on the passage of time
Sometimes we actually do want to wait for the passage of time.
e.g.
- simulating user pauses in interaction
The ‘user’ is not modelled by the application. The ‘user’ is modelled by the automated execution code. Therefore there is no ‘state’ to wait for.
Adding a Thread.sleep
into the code can be useful. Note: if I am simulating a user pause then the Thread.sleep
will be hidden behind an abstraction like User.shortThink()
, User.longThink()
, User.coffeeBreak()
which would randomly choose different time periods to pause.
I often use this when automating real life actions on applications which try to detect if you are a bot, and restrict your access if they believe you have automated their systems.
I rarely use this approach when automating an application to support my testing or for asserting on acceptance conditions.
Temporarily when I can’t identify the correct state based wait yet
When automating applications I will invariably encounter moments where I simply cannot identify a good way to synchronise on the state of the application.
At this point in time I may introduce a time based wait.
Since I know that this can introduce intermittency into my execution I have to make it clear in the code that this needs to be a temporary solution.
I wouldn’t use a User.thinksFor(5)
because later review of the code would make me believe that I did intend to have a user pause.
Instead I would use an abstraction like:
// TODO: need to identify state sync
// - tried waiting for button enabled 20200403 13:20
// - tried waiting for message to change 20200404 16:20
HackTimeWait.waitFor(5);
This lets me know what I tried (and failed), and I can see that this isn’t code I want to use very often.
And the TODO
allows me to find these easily in my IDE and in my code base.
As the pause in a polling mechanism
While I try to use the WebDriverWait
polling mechanism, sometimes it isn’t appropriate because I’ll be waiting for database state, or file system state.
I might use awaitility which provides a generic waiting mechanism (and which I cover in the synchronisation course)
Sometimes I will create my own polling mechanism, and I have to use a Thread.sleep
to pause before retrying the polling condition.
Tactical Solution
When I’m knocking up a quick tactical solution to get something done.
Then I may well start with Thread.sleep
to mark out the points in my code where I need to have a proper synchronisation if I want the code to become strategic.
As the code becomes more strategic, I refactor out the Thread.sleep
and replace with state synchronisation mechanisms.
Very often, when I’m working with this type of code, I’m working in Debug
mode anyway and use ‘breakpoints’ to allow me to identify synchronisation points and state I might synchronise on.
This type of solution is ’tactical’. Each time I run it, I try to make it more robust, identify better synchronisation and increase the use of abstractions.
Any others?
I couldn’t think of any other occasions where I use Thread.sleep
Are there any I missed?
You can learn Synchronisation in depth on my LinkedIn Learning course
Related Reading
- A summary of this blog post was posted to LinkedIn on 20200610