I'm using parametrized fixtures but I don't find the way ids are generated practical.
I'd like to fall back on the way it's generated when using pytest.mark.parametrize
.
I've seen that it's possible to provide a callable as the ids
keyword argument in pytest.fixture
(and it works), but I was wondering if there was already an implemented callable that could serve this specific purpose. Is there some internal I could replace get_id
with?
I include a MRE for illustrating my issue below.
test_ids.py
:import pytest
def add3(a, b, c):
return a + b + c
@pytest.mark.parametrize("a,b,c", [
(1, 2, 3),
(4, 5, 6),
])
def test_add_with_parametrize(a, b, c):
assert a + b + c == add3(a, b, c)
@pytest.fixture(params=[(1, 2, 3), (4, 5, 6)])
def parametrized_fixture(request):
return request.param
def test_add_with_parametrized_fixture(parametrized_fixture):
a, b, c = parametrized_fixture
assert a + b + c == add3(a, b, c)
def get_id(val):
return f"{val!r}"
@pytest.fixture(params=[(1, 2, 3), (4, 5, 6)], ids=get_id)
def parametrized_fixture_bis(request):
return request.param
def test_add_with_parametrized_fixture_bis(parametrized_fixture_bis):
a, b, c = parametrized_fixture_bis
assert a + b + c == add3(a, b, c)
pytest -v
============================= test session starts =============================
platform linux -- Python 3.11.11, pytest-8.3.5, pluggy-1.5.0 -- /home/vmonteco/.pyenv/versions/3.11.11/envs/3.11_pytest/bin/python
cachedir: .pytest_cache
rootdir: /home/vmonteco/code/MREs/MRE_pytest_ids
collected 6 items
test_ids.py::test_add_with_parametrize[1-2-3] PASSED [ 16%]
test_ids.py::test_add_with_parametrize[4-5-6] PASSED [ 33%]
test_ids.py::test_add_with_parametrized_fixture[parametrized_fixture0] PASSED [ 50%]
test_ids.py::test_add_with_parametrized_fixture[parametrized_fixture1] PASSED [ 66%]
test_ids.py::test_add_with_parametrized_fixture_bis[(1, 2, 3)] PASSED [ 83%]
test_ids.py::test_add_with_parametrized_fixture_bis[(4, 5, 6)] PASSED [100%]
============================== 6 passed in 0.01s ==============================
The change you observe in test ids generation isn't due to the use of parametrized fixtures, but to the way pytest generates these ids depending on the parameters types:
Numbers, strings, booleans and None will have their usual string representation used in the test ID. For other objects, pytest will make a string based on the argument name:
In your MRE, while you were passing parameters as integers in your first test, you're now passing them as a tuple in your second one, so the id is now based on the argument name as stated above.
def test_add_with_parametrize(a: int, b: int, c: int): ...
def test_add_with_parametrized_fixture(parametrized_fixture: tuple): ...
For types that aren't numbers, strings, booleans or None, you can either provide a callable to generate these ids as you mentioned in your post or you can override the ids generation behavior with the pytest_make_parametrize_id hook in conftest.py
def pytest_make_parametrize_id(config, val, argname):
return f"{val!r}"
test_ids.py
:
import pytest
def add3(a, b, c):
return a + b + c
@pytest.mark.parametrize("a,b,c", [
(1, 2, 3),
(4, 5, 6),
])
def test_add_with_parametrize(a, b, c):
assert a + b + c == add3(a, b, c)
@pytest.fixture(params=[(1, 2, 3), (4, 5, 6)])
def parametrized_fixture(request):
return request.param
def test_add_with_parametrized_fixture(parametrized_fixture):
a, b, c = parametrized_fixture
assert a + b + c == add3(a, b, c)
@pytest.fixture(params=[(1, 2, 3), (4, 5, 6)])
def parametrized_fixture_bis(request):
return request.param
def test_add_with_parametrized_fixture_bis(parametrized_fixture_bis):
a, b, c = parametrized_fixture_bis
assert a + b + c == add3(a, b, c)
Output
test_ids.py::test_add_with_parametrize[1-2-3] PASSED [ 16%]
test_ids.py::test_add_with_parametrize[4-5-6] PASSED [ 33%]
test_ids.py::test_add_with_parametrized_fixture[(1, 2, 3)] PASSED [ 50%]
test_ids.py::test_add_with_parametrized_fixture[(4, 5, 6)] PASSED [ 66%]
test_ids.py::test_add_with_parametrized_fixture_bis[(1, 2, 3)] PASSED [ 83%]
test_ids.py::test_add_with_parametrized_fixture_bis[(4, 5, 6)] PASSED [100%]