Python 使用夹具返回值作为mark.parametrize()中的值

Python 使用夹具返回值作为mark.parametrize()中的值,python,pytest,Python,Pytest,我的问题是-是否可以使用夹具的返回值作为参数化中的值? 问题是-我希望动态获取参数化的可能值(例如,虚拟服务器上的可用系统)。当其中一个装置创建虚拟服务器时,我可以访问这些。测试如下所示(伪代码): 这样,为每个会话添加一台服务器,然后在其上运行所有测试,会话结束后,删除服务器。但是有没有一种方法可以在@pytest.mark.parametrize中获取可用的系统,而不用显式地列出它们(静态地作为parametrize中的列表),使用会话开始时添加的服务器方法?这样,每个系统将在单独的测试中运

我的问题是-是否可以使用夹具的返回值作为参数化中的值? 问题是-我希望动态获取参数化的可能值(例如,虚拟服务器上的可用系统)。当其中一个装置创建虚拟服务器时,我可以访问这些。测试如下所示(伪代码):

这样,为每个会话添加一台服务器,然后在其上运行所有测试,会话结束后,删除服务器。但是有没有一种方法可以在@pytest.mark.parametrize中获取可用的系统,而不用显式地列出它们(静态地作为parametrize中的列表),使用会话开始时添加的服务器方法?这样,每个系统将在单独的测试中运行

我尝试在另一个fixture中使用test_server,然后返回列表(与test_server fixture返回test_server的方式相同,但我不能将其用作参数化中的值-因为在任何测试中调用test_server fixture之前都会对decorator进行评估,而获取列表取决于test_server fixture

这将是理想的:

[tests.py]

@pytest.mark.parametrize('system',[systems_list <- dynamically generated
                                             when the server is created])

def test_basic_server(test_server,system):
    test_server.install(system)
    test_server.run_checks()
    test_server.uninstall(system)
[tests.py]

@pytest.mark.parametrize('system',[systems_list我想你可能无法直接实现你想要的。因为
@pytest.mark.parametrize
在收集过程中被调用,而fixture将在收集完成后被调用

但是我有另一种方法来实现类似的结果,主要是通过扩展pytest插件
pytest\u generate\u tests
和使用method
metafunc.parametrize

这是我的解决办法。 在conftest.py中

class System(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<System '{}'>".format(self.name)

def get_available_systems():
    return [System('A'), System('B'), System('C')]


def pytest_generate_tests(metafunc):
    if 'system' in metafunc.fixturenames:
        available_systems = get_available_systems()

        metafunc.parametrize('system', available_systems)
这是输出,您可以访问测试中的每个系统

collected 3 items

test_01.py::test_basic_server[system0] <System 'A'>
PASSED
test_01.py::test_basic_server[system1] <System 'B'>
PASSED
test_01.py::test_basic_server[system2] <System 'C'>
PASSED

我能够解决一个类似的问题,即我必须生成用于动态参数化的测试数据:

class TestFilters(object):
 cls_testdata1 = []

def setup_class(cls):
 r = []
 for i in range(5):
   r.append((x, y, z))
 TestFilters.cls_testdata1 = r

@pytest.mark.parametrize("filter_id", list(range(5)))
def test_func(self, filter_id):
    params = TestFilters.cls_testdata1[filter_id]


<>这将支持动态添加参数,只是需要预先确定测试的数量。

是的,我一直在研究Meta Afunc,这是一个有效的方法,但仍然需要在测试开始之前添加另一个服务器来收集系统列表。ILL必须考虑多种方法。(超过20个),返回基于可用内容的动态列表。平均而言,这意味着超过300个案例,现在作为一个测试运行-因此您可以看到,如果Parameterize可以吞下列表并生成单独的案例,这将是一件好事。不过,我将深入研究它,也许使用metafunc我会有所收获。谢谢:)实际上,如果我在conftest.py的评估过程中设法(物理地)添加了一个服务器,然后访问它的方法来获取我需要的列表,存储它们,然后在pytest_generate_tests()中使用,表面上这正是我需要的:)这不是最干净的解决方案,但这样可以完成任务,而且我不必维护在任何给定时刻都可能发生变化的数百个变量。是的,我认为在不同的服务器上作为单独的测试运行测试是一个好主意(通过使用
参数化
),使测试结果更清晰,更容易找到故障原因。也希望了解更整洁的解决方案
collected 3 items

test_01.py::test_basic_server[system0] <System 'A'>
PASSED
test_01.py::test_basic_server[system1] <System 'B'>
PASSED
test_01.py::test_basic_server[system2] <System 'C'>
PASSED
def pytest_generate_tests(metafunc):
    if 'system' in metafunc.fixturenames:
        if hasattr(metafunc.config, 'available_systems'):
            available_systems = metafunc.config.available_systems
        else:
            available_systems = get_available_systems()
            metafunc.config.available_systems = available_systems
        metafunc.parametrize('system', available_systems)
class TestFilters(object):
 cls_testdata1 = []

def setup_class(cls):
 r = []
 for i in range(5):
   r.append((x, y, z))
 TestFilters.cls_testdata1 = r

@pytest.mark.parametrize("filter_id", list(range(5)))
def test_func(self, filter_id):
    params = TestFilters.cls_testdata1[filter_id]