Pytest:如何使用夹具返回的列表对测试进行参数设置?

时间:2018-10-11 15:54:14

标签: python pytest

我想对一个测试进行参数化,该列表由诸如此类的夹具动态创建:

@pytest.fixture
def my_list_returning_fixture(depends_on_other_fixtures):
    return ["a dynamically created list which", depends_on_other_fixtures]

我该如何实现?或者,如何确保a certain fixture gets called first-在此问题发生之前就可以解决。


我已经尝试过的东西

  • 我试图用夹具对测试进行参数化(这会导致错误,因为python认为我想移交函数本身):

    @pytest.mark.parametrize(
        "an_element_from_the_list_of_my_fixture", 
        my_list_returning_fixture
    )
    def test_the_list(an_element_from_the_list_of_my_fixture):
        print(an_element_from_the_list_of_my_fixture)
    

    my_list_returning_fixture()之类的普通函数一样调用灯具也会导致错误! Python不知道如何填充固定装置的“参数”(实际上只是其他固定装置),并显示有关传递的参数太少的错误消息...

    因此,我需要pytest来注入depends_on_other_fixtures依赖项,因此不能像普通函数那样调用它。

  • 我还试图像这样在列表固定装置和测试之间插入另一个固定装置:

    @pytest.fixture(params=my_list_returning_fixture)
    def my_interposed_parametrized_fixture(request):
        return request.param
    
    def test_the_list(my_interposed_parametrized_fixture):
        ...
    
  • 我也尝试使用间接参数化,但是它也不起作用...


使用静态列表很容易

我知道很容易使用给定的list参数化测试,就像这样:

the_list = [1, 2, 3]
@pytest.mark.parametrize("an_element_from_the_list", the_list)
def test_the_list(an_element_from_the_list):
    print(an_element_from_the_list)

这将导致三个测试。列表中的每个元素一个。

2 个答案:

答案 0 :(得分:2)

简短的答案是,您无法按照自己想要的方式进行操作,即无法通过夹具https://github.com/pytest-dev/pytest/issues/2155进行操作。基本上,必须预先知道产生或返回的事物数量,以便pytest正确计算夹具和测试依赖图。

看来,唯一的方法是在将列表元素传递给任何pytests的装饰器之前,先对其进行修复。这是一个与您的其他问题相关的示例,表明无法通过使用生成器解决该问题:

import pytest

def gen_lines():
    with open('file_that_does_not_exist') as f:
        yield from f

@pytest.fixture(scope='session')
def create_file():
    with open('file_that_does_not_exist', 'w') as f:
        print('ABC', file=f)
        print('DEF', file=f)

@pytest.fixture(params=gen_lines())
def line_fixture(request):
    return request.param

def test_line(line_fixture):
    assert True

当pytest将生成器转换为列表时,这将在收集时失败。出于相同的原因,在line_fixture的{​​{1}}上添加依赖项也无济于事。

此时,您唯一的实际选择是在模块加载时或之前运行create_file

create_file

该列表本身不必是静态的。只是无法通过灯具创建。但是不要让那阻止你。您可以将用于定义和运行import pytest def gen_lines(): with open('file_that_does_not_exist') as f: yield from f def create_file(): with open('file_that_does_not_exist', 'w') as f: print('ABC', file=f) print('DEF', file=f) create_file() @pytest.fixture(params=gen_lines()) def line_fixture(request): return request.param def test_line(line_fixture): assert True 的代码放在单独的模块中,然后将其作为实用程序随时随地导入。这样可以掩盖所有混乱的细节,并使您的代码看起来像使用灯具一样干净。

答案 1 :(得分:1)

这似乎是enter image description here的副本。

根据设计,这是不可能的:“夹具”的概念保留给测试执行,而“参数”的概念保留给测试集合。请参阅this question