Skip to main content

A testing (and partial) replacement for the time package, for fully-controlled time-dependent tests.

Project description

An owl emoji

Simulated Time

A testing (and partial) replacement for Python's time package, for fully-controlled time-dependent tests.

PyPI



Testing functions that depend on time is always tricky, and can take long. To save time and avoid relying on time.sleep(), this package allows to fast-forward time arbitrarily.

It implements the functions stime.time() and stime.monotonic().


Note: This package in not meant to replace time in production! Only in testing environments!

Usage

The idea is to make your code to use stime.test() instead of time.test() while it is being tested.

Ideally, the code you want to test is receiving a time source through dependency injection, like the Timer class in the example below.

If the code you are testing is not using dependency injection, it is likely that you can still override the time function in your tests. That is less elegant, but can be a fair trade-off to avoid having its test suite rely on time.sleep().

Once your code is using stime, you can precisely control the output of stime.time() (or stime.monotonic()) using stime.reset() and stime.tick():

  • tick(n): increments the current time by n seconds (e.g. 1.3 seconds)
  • reset(t): (re-)sets the current time to the timestamp t (e.g. 1561120200)

Example

Find the full code for this example in examples/timer!

# test_timer.py

import unittest
import stime # ①
from timer import Timer # your package with time-dependent functions to be tested

class TestTimer(unittest.TestCase):

    def test_timer_rings_for_five_seconds_starting_at_alarm_time(self):
        # create a new timer using stime as a time source
        cooking_timer = Timer(time_source=stime)
        cooking_timer.set_alarm(1561120200) # Unix timestamp for 21 June 2019 around noon

        stime.reset(1561120199) # ② a second before alarm time
        is_ringing = cooking_timer.is_ringing() # calls stime.time() because it is the timer time_source
        self.assertEqual(is_ringing, False, "expected the timer NOT to ring before alarm time")

        stime.reset(1561120200) # ③ exactly alarm time
        is_ringing = cooking_timer.is_ringing() # calls stime.time() because it is the timer time_source
        self.assertEqual(is_ringing, True, "expected the timer to ring at alarm time")

        stime.tick(5) # ④ 5 seconds after alarm time
        is_ringing = cooking_timer.is_ringing() # calls stime.time() because it is the timer time_source
        self.assertEqual(is_ringing, True, "expected the timer to be ringing 5 seconds after alarm time")

        stime.tick() # ⑤ add 1 more second
        is_ringing = cooking_timer.is_ringing() # calls stime.time() because it is the timer time_source
        self.assertEqual(is_ringing, False, "expected the timer NOT to be ringing 6 seconds after alarm time")

# [...]
  • ① Import stime where you would have imported time if it wasn't testing.
  • ② Set the current time to whatever is convenient...
  • ③ Reset it as often as needed...
  • ④ Fast-forward when convenient...
  • ⑤ or progress one second at a time!

Development

Getting started

Optionally, create a virtual environment for this project and activate it.

python -m venv timer_venv # assuming Python 3
. timer_venv/bin/activate

Then do your thing!

# run the example test suite:
python test_timer.py

# once you're done deactivate the virtual environment if you use one:
deactivate

Release

# Install the latest setuptools and wheel (in a virtual environment eventually)
pip install --upgrade setuptools wheel

# Update the package version number and tag it:
vim setup.py
git tag -a 'v1.0.0' -m 'Initial release'
git push origin master --tags

# Build the distribution files
make build

# And upload them to PyPI
make upload_to_pypi

Credits

The owl emoji in the header was rendered from an SVG that belongs to Google and was published under the Apache License v2.0 as part of Noto Emoji.

License

stime
Copyright (C) 2019 Gonzalo Bulnes Guilpain

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stime-1.0.0.tar.gz (4.4 kB view details)

Uploaded Source

Built Distribution

stime-1.0.0-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file stime-1.0.0.tar.gz.

File metadata

  • Download URL: stime-1.0.0.tar.gz
  • Upload date:
  • Size: 4.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.6.8

File hashes

Hashes for stime-1.0.0.tar.gz
Algorithm Hash digest
SHA256 5bf56469afe6194c95a2c8a47200eaff008d488e089026c1a5da9e770e12104f
MD5 05a27231de27638a3de13c9d4304782a
BLAKE2b-256 dc8d943ef63770aecbc93ed7805ea58bfec5a44c1bab7887cf94ab28537dab8a

See more details on using hashes here.

File details

Details for the file stime-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: stime-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 16.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.6.8

File hashes

Hashes for stime-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a911b381c5c31dce29a4d6f5547248fc664fae2701d761639e832e96dfc5eaf0
MD5 304d410a742177909e460e7bfb44b79a
BLAKE2b-256 fb0c7217618901c3d87beb13f59287170a4859c2b20cdbdd60a4a0efd6fbc04d

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page