首页 > 解决方案 > 在参数化夹具中缓存测试数据

问题描述

我有各种使用通用数据的测试用例。我使用pytest夹具来缓存测试数据并加快测试速度。

例如:

@pytest.fixture(scope='module')
def data():
    large_data = download('XYZ')
    return large_data

def test_foo(data):
    pass

def test_bar(data):
    pass

我想将测试扩展到两个数据集。蛮力解决方案是:

@pytest.fixture(scope='module')
def data1():
    large_data = download('XYZ')
    return large_data

@pytest.fixture(scope='module')
def data2():
    large_data = download('ABC')
    return large_data

def test_foo1(data1):
    pass

def test_foo2(data2):
    pass

def test_bar1(data1):
    pass

def test_bar2(data2):
    pass

现在的问题是这test_bar是通用的。从某种意义上说,测试程序独立于数据。因此,复制它是一个坏主意。

所以,我决定使用如下间接参数:

@pytest.fixture(scope='module')
def data(request):
    if request.param == 1:
       large_data = download('XYZ')
    if request.param == 2:
       large_data = download('ABC')
    return large_data

@pytest.mark.parametrize('data', [1], indirect=True)
def test_foo1(data):
    pass

@pytest.mark.parametrize('data', [2], indirect=True)
def test_foo2(data):
    pass

@pytest.mark.parametrize('data', [1, 2], indirect=True)
def test_bar(data):
    pass

但现在我失去了缓存优势。下载数据以供测试。如何告诉 pytest 缓存参数化夹具的数据?

标签: python-3.xpytest

解决方案


我找到了一个(非理想的)解决方案。这个想法是为每个测试数据(不能很好地扩展)定义一个固定装置,然后使用“包装器”参数化固定装置来返回它们的值。

@pytest.fixture(scope='module')
def data1():
    large_data = download('XYZ')
    return large_data

@pytest.fixture(scope='module')
def data2():
    large_data = download('ABC')
    return large_data

@pytest.fixture(scope='module')
def data(request):
    
    return request.getfixturevalue(request.param)

def test_foo1(data1):
    pass

def test_foo2(data2):
    pass

@pytest.mark.parametrize('data', ['data1', 'data2'], indirect=True)
def test_bar(data):
    pass

我已经验证过(至少在这个例子中)每个数据集都被下载一次,而且只下载一次。然而,我很想知道是否有“更清洁”的解决方案。


推荐阅读