Mocking the system time
Testing your shell scripts can be complicated enough already but when
you start to incorporate time based test scenarios you can quickly find
yourself in the land of fragile tests and intermittent failures. By
adding a small command line utility, called
faketime, to your toolbox
you can make your chronology related tests more reliable and
To start we’ll install
faketime. This focused little binary allows you
to explicitly set the system time for which ever command you pass to it.
On Fedora systems the install is as simple as:
sudo dnf install libfaketime
First we’ll run a normal
date command to ensure everything is as we expect.
$ date Sat 30 May 13:27:16 BST 2020
If we want to run our commands with a specific, and different date, we
faketime when we run them.
faketime '2008-12-24 08:15:42' date Wed 24 Dec 08:15:42 GMT 2008
This allows you to test edge cases, such as behaviour on a leap day, or start your sequence of tests from a known good point. When testing systems that have longer waits between parts of their functionality you can run the commands with explicit times and ensure you handle each case.
# create the batch with a known good time faketime '2008-10-24 08:15:42' write-batch.py # test the handling of expired records by # setting the time forward immediately faketime '2008-12-24 08:15:42' process-batch.py --expiry 31 WARNING: Monthly data is out of stale. Older than 31 days
If you’re writing in a higher level language than shell there are
sometimes more specific testing libraries to support this kind of
functionality, such as
Timecop in ruby.
faketime can still be handy when you’re working with a language that lacks such niceties or
are running in a constrained environment. The following example shows
the time being explicitly set for an entire language runtime but still
progress forward within the process.
faketime '2008-12-24 08:15:42' ruby -e 'puts Time.new ; sleep 5 ; puts Time.new' 2008-12-24 08:15:42 +0000 2008-12-24 08:15:47 +0000
And for old times sake here it is faking the time for a
faketime '2008-12-24 08:15:42' perl -e 'print localtime . "\n"' Wed Dec 24 08:15:42 2008
faketime is a very niche tool that provides flexibility in a narrow
set of use cases. You won’t need it often but when you do it’s much
easier to install it than try to kludge in your own implementation.