I have to a test a scenario where one parameter is dependent on other. I tried using the pytest hook pytest_generate_test
but i'm not sure how to pass a retrieve the value in hook which is parametrized in the 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}")
Output:
============================= 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 ===============================
Expected output:
============================= 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 ===============================
I know I have hard coded to get the first element of the list service = apps[0]
i'm not sure how can we get the parameter passed in test can be retrieved in pytest_generate_tests
To keep explain it in simple way
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')]
Unless I missed some point in your question and all you want is a slightly odd product that you have already created in your mock example, then you should IMHO just use it as a helper function to generate the parameters for the parametrize
decorator:
import logging
from itertools import product
import pytest
def app_service_product(apps, common_services):
return list(product(apps, common_services)) + [[a, a] for a in apps]
@pytest.mark.parametrize(
"app, service",
app_service_product(["app1", "app2", "app3"], ["dns", "dhcp"]),
)
def test_example(app, service):
logging.info(f"App: {app}, ServiceName: {service}")