Stub Sleeps in Tests
Book,Clock and Hammer by focusonmore.com is licensed under CC BY
I’m doing another short post here on testing code. I’ve observed that sometimes sleeps/delays find their way into production. A quick example of this would be for a retry loop (e.g., HTTP requests). When testing the code concerning these areas, you are taking on the duration of the sleep in your test suite which is slow and undesirable.
To combat the added delay in sleeps during tests, my recommendation is to stub/mock out the sleep method. Depending on the language, there are many ways to handle this. With Ruby using Minitest and Mocha, you would do the following:
# Class that sleeps for five 1 second iterations, building an array of [0..4]
class SleepyObject
def self.do_work
results = []
5.times do |index|
results << index
sleep(1)
end
results
end
end
# Minitest and Mocha are needed for testing/stubbing
require 'minitest/autorun'
require 'mocha'
require 'mocha/minitest'
# Test class
class SleepyObjectTest < Minitest::Test
# Takes 5 seconds to run
def test_with_sleeps
assert(0..4, SleepyObject.do_work)
end
# Takes pretty much 0 seconds to run
# We are also asserting that five calls to `sleep` do happen
def test_without_sleeps
SleepyObject.expects(:sleep).times(5)
assert(0..4, SleepyObject.do_work)
end
end
When we run the above code, we see the following:
Run options: -v --seed 14433
# Running:
SleepyObjectTest#test_with_sleeps = 5.02 s = .
SleepyObjectTest#test_without_sleeps = 0.00 s = .
Finished in 5.018095s, 0.3986 runs/s, 0.5978 assertions/s.
2 runs, 3 assertions, 0 failures, 0 errors, 0 skips
The tests using stubs execute quickly, and we still retain the ability to assert that sleeps are happening. This is a win-win in my books.
It can be a bit difficult to figure out what tests in your test suite that is affected by sleep durations. As the test creator, you’ll likely have a good idea of any sleep/delays in your test execution as you run them in isolation during development. I did find the following article that presents a novel approach to identify which tests have sleeps in their execution path.