Pytest:如何使用从夹具返回的列表参数化测试? [英] Pytest: How to parametrize a test with a list that is returned from a fixture?

查看:117
本文介绍了Pytest:如何使用从夹具返回的列表参数化测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用由夹具动态创建的列表来参数化测试:

I want to parametrize a test with a list which is created dynamically by a fixture like so:

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

我怎样才能做到这一点?或者,我如何确保 某个固定装置首先被调用 - 这会在它发生之前解决这个问题.

How can I achieve that? Alternatively, how can I ensure that a certain fixture gets called first - this would solve this problem before it even occurs.

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

  • I tried to parametrize the test with the fixture (which just results in errors because python thinks I want to hand over the function itself):

@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()这样的普通函数一样调用fixture也会导致错误!Python 不知道如何填充夹具的参数"(实际上只是其他夹具)并显示关于传递的参数太少的错误消息......

Calling the fixture like a normal function like my_list_returning_fixture() just results in errors, too! Python doesn't know how to fill the "parameters" of the fixture (which are actually just other fixtures) and displays an error message about too few passed arguments...

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

Therefore I need pytest to inject the depends_on_other_fixtures dependencies, so I can't call it like a normal function.

我还尝试在列表夹具和测试之间插入另一个夹具,如下所示:

I also tried to interpose another fixture between the list fixture and the test like so:

@pytest.fixture(params=my_list_returning_fixture)
def my_interposed_parametrized_fixture(request):
    return request.param

def test_the_list(my_interposed_parametrized_fixture):
    ...

  • 我也尝试过间接参数化,但它也不起作用......

  • I also tried to play around with indirect parametrization but it didn't work either...

    我知道使用给定的 list 参数化测试很容易,如下所示:

    I know it is easily possible to parametrize a test with a given list like so:

    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)
    

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

    This will lead to three tests. One for each element in the list.

    推荐答案

    简短的回答是你不能按照你想要的方式去做,即通过fixtures:https://github.com/pytest-dev/pytest/issues/2155.基本上,pytest 必须预先知道产生或返回的事物的数量,以便正确计算夹具和测试依赖关系图.

    The short answer is that you can't do it the way you want, i.e., through fixtures: https://github.com/pytest-dev/pytest/issues/2155. Basically, the number of things yielded or returned has to be known up front for pytest to properly compute the fixture and test dependency graph.

    似乎唯一的方法是在将列表元素传递给任何 pytests 的装饰器之前修复它们.这是一个与您的其他问题相关的示例,表明该问题无法通过生成器解决:

    It appears that the only way is to fix the list elements before passing them to any of pytests's decorators. Here is an example, related to your other question, showing that the problem can not be solved by say a generator:

    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 将您的生成器转换为列表时,这将在收集时失败.出于同样的原因,在 create_file 上添加对 line_fixture 的依赖也无济于事.

    This will fail at collection time when pytest turns your generator into a list. Adding a dependency to line_fixture on create_file won't help either for the same reason.

    此时您唯一真正的选择是在模块加载时或之前运行 create_file.

    Your only real option at this point is to run create_file at module load time or before.

    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
    

    该列表本身不必是静态的.它不能由夹具创建.但不要让它阻止你.您可以将用于定义和运行 create_file 的代码放入一个单独的模块中,然后将其作为实用程序导入到任何需要的地方.这将掩盖所有杂乱的细节,并使您的代码看起来与使用设备时一样干净.

    The list does not have to be static per-se. It just can't be created by a fixture. But don't let that stop you. You can put the code for defining and running create_file into a separate module, and just import it wherever you need it as a utility. That will obscure all the messy details and make your code look about as clean as it would with fixtures.

    这篇关于Pytest:如何使用从夹具返回的列表参数化测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆