python - 不同案例的pytest参数化 fixture

标签 python testing pytest

我有几个测试用例和测试函数,不同的函数测试用例列表是不同的。这可以使用 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/

相关文章:

testing - 如何在守夜人测试中绕过recaptcha人工检查?

Silverlight 测试 : Watin vs Selenium comparison

pytest - 使用 pytest 运行相关测试

python - 为什么 pycharm 无法识别我的 pytest 测试并显示测试输出?

php - Pact for PHP - 来自模拟服务器的 404 响应代码

python - 如何在测试中为多个函数重用相同的模拟

python - 从 tf.distributions.Categorical 输出层创建 softmax

python - 在 rdflib 命名空间中创建 unicode 项时出现 Unicode 解码错误

python - py拼写检查器 : do not split URL

python - 如何在 django 模板中呈现有序字典?