如何在pytest fixture中使用MonkeyPatch上下文管理器设置环境变量?

0 投票
1 回答
32 浏览
提问于 2025-04-13 19:50

我没有使用类或者测试用例,只是用pytest的函数(我想保持这样)。

这个方法不行:

@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"])

这个方法可以:

@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"])

我希望能避免像这样到处传递monkeypatch的工具。我原以为可以用MonkeyPatch把这个过程简化成一个单一的工具。难道我对MonkeyPatch作为上下文管理器的理解有误吗?

整个pytest的工具魔法和类型提示不太兼容,所以我真的想尽量减少需要传递的工具(同时又不想使用测试用例和类)。

1 个回答

0

你只需要用到 context 来在一个函数里做一些更改和撤销这些更改,这个时间是有限的。否则,使用 monkeypatch 的补丁范围就会受到使用它的工具的限制。

根据文档

所有的修改会在请求的测试函数或工具完成后被撤销。如果设置或删除操作没有找到指定的目标,raising 参数会决定是否抛出 KeyError 或 AttributeError。

要在一个有限的范围内撤销工具所做的修改,可以使用 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

撰写回答