我有几个测试用例和测试函数,不同的函数测试用例列表是不同的。这可以使用 pytest.mark.parametrize
轻松完成。我的额外需求是加载一个资源(在我的例子中是一个文件),我希望这个文件在每个测试 session 中只加载一次并缓存。
下面是一个说明我想要的例子。它正在工作,但我想找到一种方法来使用 pytest fixtures 或其他一些缓存机制,这样我就不必自己进行缓存并拥有 pars=load_file(pars)
行每个测试函数。
有人可以解释一下如何使用 pytest 做到这一点吗?
import pytest
case_1 = dict(label='case_1', spam=1)
case_2 = dict(label='case_2', spam=2)
case_3 = dict(label='case_3', spam=3)
_cache = {}
def load_file(pars):
if pars['label'] in _cache:
print('load_file from cache', pars)
return _cache[pars['label']]
else:
print('load_file loading', pars)
pars['file'] = pars['label'] + ' spam!'
_cache[pars['label']] = pars
return pars
@pytest.mark.parametrize('pars', [case_1, case_2])
def test_a(pars):
pars = load_file(pars)
print('test_a', pars)
@pytest.mark.parametrize('pars', [case_2, case_3])
def test_b(pars):
pars = load_file(pars)
print('test_b', pars)
@pytest.mark.parametrize('pars', [case1, case_2, case_3])
def test_c(pars):
pars = load_file(pars)
print('test_c', pars)
### more tests here for various combinations of test cases
最佳答案
第一个也是最明显的解决方案是使用 session 范围的固定装置。但需要重构测试文件,提前加载所有已知文件。
import pytest
@pytest.fixture(scope='session')
def pars_all():
cache = {}
for case in [case_1, case_2, case_3]:
cache[case['label']] = 'case {} content'.format(case)
yield cache
# optionally destroy or unload or unlock here.
@pytest.fixture(scope='function')
def pars(request, pars_all):
label = request.param
yield pars_all[label]
@pytest.mark.parametrize('pars', ['case_1', 'case_2'], indirect=True)
def test(pars):
pass
请注意间接参数化。这意味着将准备 pars
fixture,在 request.param
中获取参数值。参数名称和 fixture 必须共享相同的名称。
session-scoped fixture(或者模块-scoped,或者类-scoped,如果你愿意的话)将只为所有测试准备一次。重要的是要注意,较宽范围的灯具可以用于较窄范围或相同范围的灯具,但不能反方向使用。
如果情况不是那么明确,也很简单,只需按需填充缓存即可:
import pytest
@pytest.fixture(scope='session')
def pars_all():
yield {}
@pytest.fixture(scope='function')
def pars(request, pars_all):
label = request.param
if label not in pars_all:
print('[[[{}]]]'.format(request.param))
pars_all[label] = 'content of {}'.format(label)
yield pars_all[label]
@pytest.mark.parametrize('pars', ['case_1', 'case_2'], indirect=True)
def test_1(pars):
print(pars)
@pytest.mark.parametrize('pars', ['case_1', 'case_3'], indirect=True)
def test_2(pars):
print(pars)
请注意,{}
对象只创建一次,因为它是 session 范围的,并且在所有测试和调用规范之间共享。所以,如果一个灯具向其中添加了一些东西,其他灯具也会看到它。您可以注意到关于如何在 test_2
中重用 case_1
:
$ pytest -s -v -ra test_me.py
======= test session starts ==========
...
collected 4 items
test_me.py::test_1[case_1] [[[case_1]]]
content of case_1
PASSED
test_me.py::test_1[case_2] [[[case_2]]]
content of case_2
PASSED
test_me.py::test_2[case_1] content of case_1
PASSED
test_me.py::test_2[case_3] [[[case_3]]]
content of case_3
PASSED
======== 4 passed in 0.01 seconds ==========
关于python - 不同案例的pytest参数化 fixture ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46913043/