在执行pytest fixture之前运行mock



我试图有条件地为不同的测试以不同的方式模拟函数范围的fixture中的某些东西,这样我就不必用几乎相同的代码创建两个完全独立的fixture。

MY_GLOB_VAR = False
def mocked_build_data():
with conditional(MY_GLOB_VAR, mock.patch(stuff)):
build_data()
class Tests:
@pytest.fixture(scope='function')
def my_fixture(self, conftest_fixtures):
inject_test_specific_data_into_db(conftest_fixtures)
mocked_build_data()
yield
cleanup_mysql()
def test_1(self, my_fixture):
assert True
@mock.patch(f'{__name__}.MY_GLOB_VAR', True)
def test_2(self, my_fixture):
assert True

在执行my_fixture之前,我需要对test_2应用mock,但它只在我进入函数体时应用。

我能以我现在的方式强行这样做吗,或者有条件地以其他方式嘲笑这场比赛吗?

您也可以在单独的夹具中移动补丁,并确保在test_2中的my_fixture之前请求它。fixture是按照测试函数参数中列出的顺序执行的,因此在签名def test(fix1, fix2):中,fixturefix1将在fix2之前执行。具体来说:

MY_GLOB_VAR = False
class Tests:
@pytest.fixture
def patch_my_glob_var(self):
with mock.patch(f'{__name__}.MY_GLOB_VAR', True):
yield
@pytest.fixture(scope='function')
def my_fixture(self):
print('MY_GLOB_VAR is', MY_GLOB_VAR)
yield
def test_1(self, my_fixture):
assert MY_GLOB_VAR is False
def test_2(self, patch_my_glob_var, my_fixture):
assert MY_GLOB_VAR is True

使用-s标志运行它应该会产生

some_test_module::Tests::test_1 MY_GLOB_VAR is False
PASSED
some_test_module::Tests::test_2 MY_GLOB_VAR is True
PASSED

另一种选择是通过usefixtures标记请求fixture,因为它返回的结果在测试中没有明确使用。不过,这将导致相同的结果,因为patch_my_glob_var仍将在my_fixture:之前进行评估

@pytest.mark.usefixtures('patch_my_glob_var')
def test_2(self, my_fixture):
...

您可以使用Pytest的间接参数化功能。

在参数化测试时使用indirect=True参数,可以在将值传递给测试之前,通过夹具接收值来参数化测试。

在您的情况下,您可以根据它接收到的值(通过request参数(模拟fixture中的对象。下面是一个说明原理的例子。

import pytest
MY_GLOB_VAR = None

@pytest.fixture(scope="function")
def my_fixture(request):
if hasattr(request, "param"):
# use it without param (default case)
global MY_GLOB_VAR
MY_GLOB_VAR = request.param
yield
# restore initial status
MY_GLOB_VAR = None

@pytest.mark.parametrize("my_fixture", [True], indirect=True)
def test_true(my_fixture):
assert MY_GLOB_VAR == True

@pytest.mark.parametrize("my_fixture", [False], indirect=True)
def test_false(my_fixture):
assert MY_GLOB_VAR == False

def test_none(my_fixture):
"""Example without parametrization"""
assert MY_GLOB_VAR is None

运行测试

pytest test_mock.py
# test_mock.py::test_true[True] PASSED
# test_mock.py::test_false[False] PASSED
# test_mock.py::test_none PASSED                                                                                                                                              ```

最新更新