如何在pytest中全局修补?

Ran*_*dra 7 python tdd pytest python-mock

我的代码使用pytest相当多.示例代码结构如下所示.整个代码库是python-2.7

core/__init__.py
core/utils.py

#feature

core/feature/__init__.py
core/feature/service.py

#tests
core/feature/tests/__init__.py
core/feature/tests/test1.py
core/feature/tests/test2.py
core/feature/tests/test3.py
core/feature/tests/test4.py
core/feature/tests/test10.py
Run Code Online (Sandbox Code Playgroud)

service.py看起来是这样的:

from modules import stuff
from core.utils import Utility


class FeatureManager:
    # lots of other methods
    def execute(self, *args, **kwargs):
        self._execute_step1(*args, **kwargs)
        # some more code
        self._execute_step2(*args, **kwargs)
        utility = Utility()
        utility.doThings(args[0], kwargs['variable'])
Run Code Online (Sandbox Code Playgroud)

所有测试feature/tests/*最终都使用了core.feature.service.FeatureManager.execute功能.但是utility.doThings(),在运行测试时,我没有必要运行.我需要它在生产应用程序运行时发生,但我不希望它在测试运行时发生.

我可以做我这样的事 core/feature/tests/test1.py

from mock import patch

class Test1:
   def test_1():
       with patch('core.feature.service.Utility') as MockedUtils:
           exectute_test_case_1()
Run Code Online (Sandbox Code Playgroud)

这会奏效.但是我Utility刚刚添加到代码库中,我有超过300个测试用例.我不想进入每个测试用例并写下这个with语句.

我可以写一个conftest.py设置一个os级环境变量,根据该环境变量core.feature.service.FeatureManager.execute可以决定不执行,utility.doThings但我不知道这是否是这个问题的一个干净的解决方案.

如果有人可以帮助我完成整个会话的全局补丁,我将不胜感激.我想with在整个会话期间对全局上面的块做我所做的事情.这件事的任何文章都会很棒.

TLDR:如何在运行pytests时创建会话范围的补丁?

Int*_*rer 19

基于当前接受的类似用例(4.5 年后)的答案,使用 unittest.mock也patch有效yield

from typing import Iterator
from unittest.mock import patch

import pytest


@pytest.fixture(scope="session", autouse=True)
def default_session_fixture() -> Iterator[None]:
    log.info("Patching core.feature.service")
    with patch("core.feature.service.Utility"):
        yield
    log.info("Patching complete. Unpatching")
Run Code Online (Sandbox Code Playgroud)

在旁边

对于这个答案,我使用了autouse=True. 在我的实际用例中,为了在逐个测试的基础上集成到我的单元测试中,我使用了@pytest.mark.usefixtures("default_session_fixture").


版本

Python==3.8.6
pytest==6.2.2
Run Code Online (Sandbox Code Playgroud)


Ran*_*dra 11

我添加了一个名为core/feature/conftest.pythis 的文件

import logging
import pytest


@pytest.fixture(scope="session", autouse=True)
def default_session_fixture(request):
    """
    :type request: _pytest.python.SubRequest
    :return:
    """
    log.info("Patching core.feature.service")
    patched = mock.patch('core.feature.service.Utility')
    patched.__enter__()

    def unpatch():
        patched.__exit__()
        log.info("Patching complete. Unpatching")

    request.addfinalizer(unpatch)
Run Code Online (Sandbox Code Playgroud)

这并不复杂.这就像在做

with mock.patch('core.feature.service.Utility') as patched:
    do_things()
Run Code Online (Sandbox Code Playgroud)

但只能在会议范围内.

  • 您的“模拟”在哪里定义或导入?```= mock.patch...``` (2认同)