Pytest Patching Sleep On Certain Condition

I am writing tests using Pytest and Python 3.6. My tests use an ENV var called online, which I use to determine whether the tests will hit the real web service or whether it will just be playback.

I want to patch sleep when the tests are not online for all the tests. When the tests are in online mode, dont patch. Is there a way to do this on pytest? My initial thought was to use a fixture that uses the env var to monkeypatch or not.

I am not sure how to go about with this?


Solution 1:

The easiest way to do this is to use an autouse fixture. The standard way is to use mock.patch to mock the function:

from unittest import mock
import pytest

@pytest.fixture(autouse=True)
def patch_sleep():
    if "ONLINE" in os.environ and os.environ["ONLINE"] == "1":
        with mock.patch("time.sleep"):
            yield
    else:
        yield

In this case the function will be patched in each test, and the patch reverted after each test. If you use autouse=True, the fixture will be invoked automatically in all tests, otherwise you have to reference it in the tests.

If you know that your environment cannot change during the test, you can use a session-scoped fixture that is invoked only once in the test session:

@pytest.fixture(autouse=True, scope="session")
def patch_sleep():
   ...

In this case, time.sleep will be patched before all tests run, and the patch reverted after all tests have finished.

If you don't want to use unittest.patch, you can use the pytest-mock plugin, which provides the mocker fixture:

@pytest.fixture(autouse=True)
def patch_sleep(mocker):
    if "ONLINE" in os.environ and os.environ["ONLINE"] == "1":
        mocker.patch("time.sleep")
        yield
    else:
        yield

You can also use monkeypatch, though that is not the usual way for patching a function:

@pytest.fixture(autouse=True)
def patch_sleep(monkeypatch):
    def dont_sleep(sec):
        pass

    if "ONLINE" in os.environ and os.environ["ONLINE"] == "1":
        monkeypatch.setattr(time, "sleep", dont_sleep)
        yield
    else:
        yield