使用夹具返回值作为 mark.parametrize() 中的值 [英] using fixture return value as value in mark.parametrize()
问题描述
我的问题是 - 是否可以将夹具的返回值用作参数化中的值?问题是 - 我想动态获取可能的值(例如,虚拟服务器上的可用系统)以进行参数化.当其中一个装置创建虚拟服务器时,我可以访问这些.测试看起来像这样(伪代码):
my question is - is it possible to use return value from fixture as a value in parametrize? The problem is - I'd like to dynamically get possible values (for example, available systems on a virtual server) for parametrize. I can access these when a virtual server is created by one of the fixtures. Tests look like this (pseudo-code-ish):
[conftest.py]
@pytest_fixture(scope='session')
def test_server(request):
test_server = Server([default_params])
test_server.add()
def fin():
test_server.delete()
request_addfinalizer(fin)
return test_server()
[tests.py]
def test_basic_server(test_server):
systems = test.server.get_available_systems()
for system in systems:
test_server.install(system)
test_server.run_checks()
test_server.uninstall(system)
def test_other(test_server):
[other tests]
etc
这样,为每个会话添加一个服务器,然后在其上运行所有测试,会话结束后,服务器被删除.但是有没有办法使用会话开始时添加的服务器方法来获取@pytest.mark.parametrize 中的可用系统而无需明确列出它们(静态地作为参数中的列表)?这样每个系统都会在单独的测试中运行.
This way, one server is added for each session, then all tests run on it, and after session ends, server is removed. But is there a way to get the available systems in @pytest.mark.parametrize without explicitly listing them (statically as a list in parametrize), using the method from server that is added when the session begins? That way each system would run in a separate test.
我尝试在另一个夹具中使用 test_server 然后返回列表(与 test_server 夹具返回 test_server 的方式相同,但我不能将其用作参数化中的值 - 因为在任何测试中调用 test_server 夹具之前对装饰器进行评估,获取列表取决于 test_server 夹具.
I tried using test_server in another fixture and then returning the list (the same way test_server is returned by test_server fixture, but I cannot use that as a value in parametrize - since decorator is evaluated before the test_server fixture is called in any test, and getting the list depends on 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)
这只是一个非常基本的例子,在我的测试中,我需要基于多个场景和值进行参数化,而当我静态执行时,我最终得到了巨大的数组.
This is just a very basic example, in my tests I need to parametrize based on multiple scenarios and values and I end up with giant arrays when I do it statically.
但原理保持不变 - 基本上:我可以在使用此夹具运行的第一次测试之前调用夹具,或者 pytest.mark.parametrize() 如何访问夹具值?
But the principle remains the same - basically: can I call the fixture before the first test using this fixture runs, or how can pytest.mark.parametrize() access fixture values?
推荐答案
我认为您可能无法直接实现您想要的.因为@pytest.mark.parametrize
是在采集过程中被调用的,而fixtures会在采集完成后被调用.
I think you may be unable to achieve what you want directly. Because @pytest.mark.parametrize
is being called during collecting, and fixtures will be called after collection completed.
但我有另一种方法来实现类似的结果,主要是通过扩展 pytest 插件 pytest_generate_tests
和使用方法 metafunc.parametrize
.https://pytest.org/latest/parametrize.html#basic-pytest-generate-tests-example
But I have an alternative way to achieve similar result, mainly by extending pytest plugin pytest_generate_tests
and using method metafunc.parametrize
.
https://pytest.org/latest/parametrize.html#basic-pytest-generate-tests-example
这是我的解决方案.在 conftest.py
Here is my solution. In 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)
在测试文件中:
def test_basic_server(system):
print(system)
这是输出,您将可以访问测试中的每个系统.
This is the output, you will have access to each system in test.
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
不好的是,每次使用fixture system
时都会调用get_available_systems
,这不是您想要的.但是我觉得添加一些额外的逻辑让查询逻辑只执行一次也不难.
The bad thing is, get_available_systems
will be called every time whenever using fixture system
, which is not what you want. But I think it's not hard to add some extra logic to make the query logic only be executed once.
例如:
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)
这篇关于使用夹具返回值作为 mark.parametrize() 中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!