Skip to main content
 首页 » 编程设计

python之使用返回列表的 fixture 参数化 pytest 函数的最佳方法是什么

2025年05月04日21lovecherry

现在我有一个看起来像这个人为示例的测试文件:

import pytest 
 
def colors(): 
    # Expensive operation 
    return ['red', 'yellow', 'blue'] 
 
@pytest.mark.parametrize('color', colors()) 
def test_colors(color): 
    assert color != 'mauve' 

这工作正常,但由于 colors() 是一项昂贵的操作,我想利用 pytest 的缓存并使其成为 session 范围的固定装置。此外,我还想使用它作为 fixture 编写其他测试,例如

def test_colors_list(colors): 
    assert len(colors) == 3 

理想情况下,我的测试文件应该是这样的

@pytest.fixture(scope='session') 
def colors(): 
    # Expensive operation 
    return ['red', 'yellow', 'blue'] 
 
@pytest.mark.parametrize('color', colors) 
def test_colors(color): 
    assert color != 'mauve' 
 
def test_colors_list(colors): 
    assert len(colors) == 3 

但这会导致错误,所以我没有正确处理这个问题。

理想情况下,我还想在 colors() 中引用其他 fixture,并仍然参数化 test_colors() 以生成多个函数。

编写这些测试的最佳方式是什么?

请您参考如下方法:

一种解决方案是在单独的函数中生成颜色,并将其结果用作灯具的 params 参数,然后您可以多次使用该参数

import pytest 
 
def colors(): 
    print('expensive') 
    return ['blue', 'red', 'mauve'] 
 
@pytest.fixture(params=colors()) 
def color(request): 
    return request.param 
 
def test_bla(color): 
    print(color, end='') 
 
def test_foo(color): 
    print(color, end='') 

如果您运行 pytest -s,您将在输出中仅看到一次字符串 expensive:

$py.test -sv 
======================== test session starts ========================= 
platform linux -- Python 3.4.3, pytest-3.4.1, py-1.5.2, pluggy-0.6.0 -- /home/nils/test/bin/python3 
cachedir: .pytest_cache 
rootdir: /home/nils/test/bla, inifile: 
collecting 0 items                                                   expensive 
collected 6 items 
 
test_bla.py::test_bla[blue] bluePASSED 
test_bla.py::test_bla[red] redPASSED 
test_bla.py::test_bla[mauve] mauvePASSED 
test_bla.py::test_foo[blue] bluePASSED 
test_bla.py::test_foo[red] redPASSED 
test_bla.py::test_foo[mauve] mauvePASSED 
 
====================== 6 passed in 0.04 seconds ====================== 

但是,昂贵的函数在导入时运行,这不是一个好的行为。