I'm not using classes or test cases I'm just using pytest functions (want to keep it that way).
This does not work:
@pytest.fixture(scope="function")
def set_env():
with MonkeyPatch.context() as mp:
mp.setenv("VAR_ONE", "123")
mp.setenv("VAR_TWO", "test")
def test_blah(set_env):
print(os.environ["VAR_ONE"])
print(os.environ["VAR_TWO"])
This does:
@pytest.fixture(scope="function")
def set_env(monkeypatch):
monkeypatch.setenv("VAR_ONE", "123")
monkeypatch.setenv("VAR_TWO", "test")
def test_blah(monkeypatch, set_env):
print(os.environ["VAR_ONE"])
print(os.environ["VAR_TWO"])
I was hoping to avoid passing around monkeypatch fixtures like this. I thought I could use MonkeyPatch
to abstract this behind a single fixture. Am I misunderstanding MonkeyPatch
as a context manager?
The whole pytest fixture magic thing doesn't play nice with type hinting so I really want to minimize the fixtures I need to pass around (while still not using test cases and classes).
You only need context
to do and undo changes for a limited time within a single function. Otherwise, the scope of the patch is limited by the scope of the fixture using monkeypatch
.
From the documentation:
All modifications will be undone after the requesting test function or fixture has finished. The raising parameter determines if a KeyError or AttributeError will be raised if the set/deletion operation does not have the specified target.
To undo modifications done by the fixture in a contained scope, use context().
import pytest, os
@pytest.fixture(scope="function")
def set_env(monkeypatch):
monkeypatch.setenv("VAR_ONE", "123")
monkeypatch.setenv("VAR_TWO", "test")
def test_one(set_env):
assert os.environ["VAR_ONE"] == "123"
assert os.environ["VAR_TWO"] == "test"
def test_two(monkeypatch):
assert "VAR_ONE" not in os.environ
with monkeypatch.context() as mp:
mp.setenv("VAR_ONE", "123")
assert os.environ["VAR_ONE"] == "123"
assert "VAR_ONE" not in os.environ