我有几个测试用例和测试函数,并且测试用例列表对于不同的函数是不同的。这可以通过pytest.mark.parametrize
轻松完成。我需要的是加载资源(在我的情况下是一个文件),我希望每个测试会话只加载一次这个文件并缓存。
下面举例说明我想要的内容。它正在工作,但我想找到一种方法来使用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
答案 0 :(得分:0)
第一个也是最明显的解决方案是使用会话范围的灯具。但是,它需要重新构建测试文件,并提前加载所有已知文件。
return database.update({ref : parseInt(number)})
.then(() => {
// Each then() should return a value or throw
return 'Update successful';
})
.catch(error => {
// handle the error however you like
console.error(error);
});
请注意间接参数化。这意味着将准备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
中的参数值。参数名称和灯具必须共享相同的名称。
对于所有测试,会话范围的装置(或模块范围,或类型范围,如果您愿意)将只准备一次。重要的是要注意,更宽的固定装置可用于更窄的范围或相同范围的固定装置,但不能用于相反的方向。
如果案例定义不明确,那就容易了,只需按需填充缓存:
request.param
注意,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)
对象只创建一次,因为它是会话范围的,并且在所有测试和/或之间共享。 callspecs。因此,如果一个灯具添加了一些东西,其他灯具也会看到它。您可以注意到{}
:
case_1
的重用方式
test_2
答案 1 :(得分:0)
在文件解析功能中简单地使用@lru_cache
也可以实现缓存技巧:
@lru_cache(maxsize=3)
def load_file(file_name):
""" This function loads the file and returns contents"""
print("loading file " + file_name)
return "<dummy content for " + file_name + ">"
通过使用pytest-cases将测试功能与测试用例分开(我是作者!),您还可以获得相同的结果,同时使整个代码更具可读性(?): / p>
from functools import lru_cache
from pytest_cases import CaseData, cases_data, CaseDataGetter, case_tags
@lru_cache(maxsize=3)
def load_file(file_name):
""" This function loads the file and returns contents"""
print("loading file " + file_name)
return "<dummy content for " + file_name + ">"
def case_1() -> CaseData:
ins = load_file('file1')
outs, err = None, None
return ins, outs, err
def case_2() -> CaseData:
ins = load_file('file2')
outs, err = None, None
return ins, outs, err
def case_3() -> CaseData:
ins = load_file('file3')
outs, err = None, None
return ins, outs, err
@cases_data(cases=[case_1, case_2])
def test_a(case_data: CaseDataGetter):
# 1- Grab the test case data
i, expected_o, expected_e = case_data.get()
# 2- Use it
# see pytest-cases usage page for suggestions
@cases_data(cases=[case_2, case_3])
def test_b(case_data: CaseDataGetter):
# 1- Grab the test case data
i, expected_o, expected_e = case_data.get()
# 2- Use it
# see pytest-cases usage page for suggestions
@cases_data(cases=[case_1, case_2, case_3])
def test_c(case_data: CaseDataGetter):
# 1- Grab the test case data
i, expected_o, expected_e = case_data.get()
# 2- Use it
# see pytest-cases usage page for suggestions
收益:
test_memoize.py::test_a[case_1] loading file file1
PASSED
test_memoize.py::test_a[case_2] loading file file2
PASSED
test_memoize.py::test_b[case_2] PASSED
test_memoize.py::test_b[case_3] loading file file3
PASSED
test_memoize.py::test_c[case_1] PASSED
test_memoize.py::test_c[case_2] PASSED
test_memoize.py::test_c[case_3] PASSED
最后,请注意,根据您的用例,您可能希望切换到案例生成器功能,这将更具可读性并且supports caching too。如果您不想明确地对案例进行硬编码,也请查看tags & filters。