首页 > 解决方案 > 如何为多个测试打补丁

问题描述

考虑我的模块"mymodule.py"

# contents of "mymodule.py"

def func1(x):
    return x * 2

我想模拟这个函数并改变它的返回。根据文档,我可以这样做:

# contents of "test_mymodule.py"

import mymodule
import pytest

@pytest.fixture
def mock_func1():
    def mock_ret(*args, **kwargs):
        return 2

def test_func1_a(monkeypatch, mock_func1):
    monkeypatch.setattr(mymodule, "func1", mock_func1)
    assert mymodule.func1(1) == 2 

def test_func1_b(monkeypatch, mock_func1):
    monkeypatch.setattr(mymodule, "func1", mock_func1)
    assert mymodule.func1(1) != 37 

但是,我不想为每个测试修补模块。monkeypatch.setattr对整个测试模块的范围进行一次的正确方法是什么test_mymodule.py

我期待这样的事情

# contents of "test_mymodule.py"

import mymodule
import pytest

@pytest.fixture
def mock_func1():
    def mock_ret(*args, **kwargs):
        return 2

monkeypatch.setattr(mymodule, "func1", mock_func1)

def test_func1_a():
    assert mymodule.func1(1) == 2 

def test_func1_b():
    assert mymodule.func1(1) != 37 

但这让我

NameError: name 'monkeypatch' is not defined

标签: pythonpytestmonkeypatching

解决方案


刚刚遇到这个答案,因为我正在尝试做类似的事情。您可以使用这样的装饰器对测试进行预处理。可以在装饰器下方添加其他 pytest 装饰mock_func_1_in_test器。

# contents of "test_mymodule.py"

import mymodule
import pytest

@pytest.fixture
def mock_func1():
    def mock_ret(*args, **kwargs):
        return 2

    return mock_ret

def mock_func_1_in_test(func):
    def inner(monkeypatch, mock_func1, *args, **kwargs):
        monkeypatch.setattr(mymodule, "func1", mock_func1)
        return func(*args, **kwargs)
    return inner

@mock_func_1_in_test
def test_func1_a():
    assert mymodule.func1(1) == 2 

@mock_func_1_in_test
def test_func1_b():
    assert mymodule.func1(1) != 37 

这如您所料:

$ pytest
================================== test session starts ===================================
platform darwin -- Python 3.6.6, pytest-3.6.0, py-1.6.0, pluggy-0.6.0
rootdir: /Users/delgadom/git/messin/pytest_test, inifile:
plugins: cov-2.5.1
collected 2 items

test_mymodule.py ..                                                                [100%]

================================ 2 passed in 0.03 seconds ================================

推荐阅读