我必须测试一个参数依赖于其他参数的场景。我尝试使用 pytest 挂钩
pytest_generate_test
但我不确定如何传递检索在测试中参数化的挂钩中的值。
import pytest
import logging
logger = logging.getLogger(__name__)
apps = ['app1', 'app2', 'app3']
def pytest_generate_tests(metafunc):
common_services = ['dns', 'dhcp']
service = apps[0]
common_services.append(service)
if "total_services" in metafunc.fixturenames:
metafunc.parametrize("total_services", common_services)
@pytest.fixture()
def total_services(request):
return request.param
@pytest.mark.parametrize("app", apps)
def test_example(app, total_services):
logging.info(f"App: {app}, ServiceName: {total_services}")
输出:
============================= test session starts ==============================
platform darwin -- Python 3.11.7, pytest-8.0.2, pluggy-1.4.0
rootdir: /private/tmp/test/tests
collected 9 items
test_example.py::test_example[dns-app1]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app1, ServiceName: dns
PASSED [ 11%]
test_example.py::test_example[dns-app2]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app2, ServiceName: dns
PASSED [ 22%]
test_example.py::test_example[dns-app3]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app3, ServiceName: dns
PASSED [ 33%]
test_example.py::test_example[dhcp-app1]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app1, ServiceName: dhcp
PASSED [ 44%]
test_example.py::test_example[dhcp-app2]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app2, ServiceName: dhcp
PASSED [ 55%]
test_example.py::test_example[dhcp-app3]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app3, ServiceName: dhcp
PASSED [ 66%]
test_example.py::test_example[app1-app1]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app1, ServiceName: app1
PASSED [ 77%]
test_example.py::test_example[app1-app2]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app2, ServiceName: app1
PASSED [ 88%]
test_example.py::test_example[app1-app3]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app3, ServiceName: app1
PASSED [100%]
============================== 9 passed in 0.01s ===============================
预期输出:
============================= test session starts ==============================
platform darwin -- Python 3.11.7, pytest-8.0.2, pluggy-1.4.0
rootdir: /private/tmp/test/tests
collected 9 items
test_example.py::test_example[dns-app1]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app1, ServiceName: dns
PASSED [ 11%]
test_example.py::test_example[dns-app2]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app2, ServiceName: dns
PASSED [ 22%]
test_example.py::test_example[dns-app3]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app3, ServiceName: dns
PASSED [ 33%]
test_example.py::test_example[dhcp-app1]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app1, ServiceName: dhcp
PASSED [ 44%]
test_example.py::test_example[dhcp-app2]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app2, ServiceName: dhcp
PASSED [ 55%]
test_example.py::test_example[dhcp-app3]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app3, ServiceName: dhcp
PASSED [ 66%]
test_example.py::test_example[app1-app1]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app1, ServiceName: app1
PASSED [ 77%]
test_example.py::test_example[app1-app2]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app2, ServiceName: app2
PASSED [ 88%]
test_example.py::test_example[app1-app3]
-------------------------------- live log call ---------------------------------
INFO root:test_example.py:21 App: app3, ServiceName: app3
PASSED [100%]
============================== 9 passed in 0.01s ===============================
我知道我已经硬编码来获取列表的第一个元素
service = apps[0]
我不确定如何才能获取测试中传递的参数可以在pytest_generate_tests
中检索
继续用简单的方式解释它
from itertools import product
apps = ['app1', 'app2', 'app3']
def cartesian_product(app, common_servcies):
return list(product(app, common_servcies))
for app in apps:
common_services = ['dns', 'dhcp']
common_services.append(app)
print(cartesian_product([app], common_services))
Output:
$ python3 test_example2.py
[('app1', 'dns'), ('app1', 'dhcp'), ('app1', 'app1')]
[('app2', 'dns'), ('app2', 'dhcp'), ('app2', 'app2')]
[('app3', 'dns'), ('app3', 'dhcp'), ('app3', 'app3')]
你几乎解决了你自己的问题。这是一种方法:
import itertools
import logging
import pytest
SERVICES_AND_APPS = []
for app in ["app1", "app2", "app3"]:
services = ["dns", "dhcp"] + [app]
SERVICES_AND_APPS.extend(itertools.product(services, [app]))
# BEGIN sort
def custom_key(service_and_app):
"""Ensure sort order of dns, dhcp, app1, app2, app3."""
custom_order = {
"dns": "a1",
"dhcp": "a2",
}
service, app = service_and_app
return custom_order.get(service, service), app
SERVICES_AND_APPS.sort(key=custom_key)
# END sort
@pytest.mark.parametrize("service,app", SERVICES_AND_APPS)
def test_example(service, app):
logging.info("app=%r, service=%r", app, service)
注释
BEGIN sort
和END sort
之间的代码确保顺序。如果您不关心顺序(一般来说,您不应该),那么您可以删除该部分,这使得脚本更易于理解且更短。custom_order
将dns
翻译为a1
,将dhcp
翻译为a2
,这确保了您正在寻找的顺序。