I have a parameterized test which takes str
, and dict
as an argument and so the name look pretty weird if I allow pytest to generate ids.
I want to generate custom ids using a function, however it seems it's not working as intended.
def id_func(param):
if isinstance(param, str):
return param
@pytest.mark.parametrize(argnames=('date', 'category_value'),
argvalues=[("2017.01", {"bills": "0,10", "shopping": "100,90", "Summe": "101,00"}),
("2017.02", {"bills": "20,00", "shopping": "10,00", "Summe": "30,00"})],
ids=id_func)
def test_demo(date, category_value):
pass
I was thinking it would return something like this
test_file.py::test_demo[2017.01] PASSED
test_file.py::test_demo[2017.02] PASSED
but it's returning this.
test_file.py::test_demo[2017.01-category_value0] PASSED
test_file.py::test_demo[2017.02-category_value1] PASSED
Could someone tell me what's wrong with this, or is there any way to achieve this?
Update:
I realize what's the issue, if_func will be called for each parameter and if I won't return str
for any parameter default function will be called. I have fix but that's also ugly.
def id_func(param):
if isinstance(param, str):
return param
return " "
Now it returns something like this,
test_file.py::test_demo[2017.01- ] PASSED
test_file.py::test_demo[2017.02- ] PASSED
The problem is even If I return empty string (i.e. return ""
)it takes the default representation. Could someone let me know why?
you can put @pytest. mark. parametrize style parametrization on the test functions to parametrize input/output values as well.
parametrize : parametrizing test functions. Parameter values are passed as-is to tests (no copy whatsoever). For example, if you pass a list or a dict as a parameter value, and the test case code mutates it, the mutations will be reflected in subsequent test case calls.
One way is to move your argvalues
to another variable and write your test like this:
import pytest
my_args = [
("2017.01", {"bills": "0,10", "shopping": "100,90", "Summe": "101,00"}),
("2017.02", {"bills": "20,00", "shopping": "10,00", "Summe": "30,00"})
]
@pytest.mark.parametrize(
argnames=('date', 'category_value'), argvalues=my_args,
ids=[i[0] for i in my_args]
)
def test_demo(date, category_value):
pass
Test execution:
$ pytest -v tests.py
================= test session starts =================
platform linux2 -- Python 2.7.12, pytest-3.2.1, py-1.4.34, pluggy-0.4.0 -- /home/kris/.virtualenvs/2/bin/python2
cachedir: .cache
rootdir: /home/kris/projects/tmp, inifile:
collected 2 items
tests.py::test_demo[2017.01] PASSED
tests.py::test_demo[2017.02] PASSED
============== 2 passed in 0.00 seconds ===============
I think it's not possible with a function (idfn
in your case), because if it's not generating label for an object the default pytest representation is used.
Check pytest site for details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With