monkeypatch
Code that reads the clock, draws random numbers or looks at environment variables gives a different answer on every run. pytest's monkeypatch fixture replaces those sources for one test and undoes every change when the test ends, pass or fail.
import random
import pytest
def roll():
return random.randint(1, 6)
# In a test, ask for monkeypatch instead.
with pytest.MonkeyPatch.context() as mp:
mp.setattr(random, "randint",
lambda low, high: 6)
print(roll(), roll())
print(1 <= roll() <= 6)The useful methods
setattr(module, "name", value)replaces an attribute, such astime.time.setenv("KEY", "value")anddelenv("KEY", raising=False)control environment variables.chdir(path)changes the current folder.
Setting os.environ or time.time by hand works too, but the change outlives the test and breaks whichever test runs next. Some things refuse to be patched: datetime.date.today belongs to a built-in type. For those, pass the clock in, as the next lesson shows.
Your task
make_token and api_base are written for you. Write test_token_uses_clock_and_random(monkeypatch), fixing time.time at 1700000000.9 and random.randint at 4242 and checking the whole token; test_api_base_from_environment(monkeypatch), setting API_BASE to http://localhost:8000/; and test_api_base_default(monkeypatch), removing API_BASE.
The explanation opens here once every check passes.