pytest 两级参数化,其中一个参数依赖于另一个参数

问题描述 投票:0回答:1

我必须测试一个参数依赖于其他参数的场景。我尝试使用 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')]
python pytest dynamicparameters
1个回答
0
投票

你几乎解决了你自己的问题。这是一种方法:

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
    ,这确保了您正在寻找的顺序。
© www.soinside.com 2019 - 2024. All rights reserved.