Skip to content Skip to sidebar Skip to footer

Pytest Parameterized Test With Custom Id Function

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 func

Solution 1:

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]
)deftest_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 in0.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.

Solution 2:

Alternatively you can also use a list comprehension to generate your ids as follows:

import pytest


values = [
    ("2017.01", {"bills": "0,10", "shopping": "100,90", "Summe": "101,00"}),
    ("2017.02", {"bills": "20,00", "shopping": "10,00", "Summe": "30,00"})
]
value_ids = [e[0] for e in values]


@pytest.mark.parametrize('date,category_value', values, ids=value_ids
)deftest_demo(date, category_value):
    pass

Assuming these tests are in test_file.py at the root of your directory, if you run pytest test_file.py --co -q, you will get the following output:

test_file.py::test_demo[2017.01]
test_file.py::test_demo[2017.02]

Solution 3:

Usually, when I want to be specific about test case being executing in the params I use named tuples as a workaround for the id funcion being executed once per param, that way a get a cleaner test description.

import pytest
from collections import namedtuple


TCase = namedtuple("TCase", "x,y,expected,description")


test_cases = [
    TCase(10, 10, 20, "10 + 10 should be 20"),
    TCase(1, 1, 2, "1 + 1 should be 2"),
]


defidfn(tc: TCase):
    return tc.description


@pytest.mark.parametrize("tc", test_cases, ids=idfn)deftest_sum(tc):
    assert tc.x + tc.y == tc.expected

Output:

example.py::test_sum[10 + 10 should be 20] PASSED                                                                           
example.py::test_sum[1 + 1 should be 2] PASSED 

So I would write your example as:

from collections import namedtuple
import pytest


TCase = namedtuple("TCase", "date,data")

my_args = [
    TCase("2017.01", {"bills": "0,10", "shopping": "100,90", "Summe": "101,00"}),
    TCase("2017.02", {"bills": "20,00", "shopping": "10,00", "Summe": "30,00"}),
]


@pytest.mark.parametrize("tc", my_args, ids=lambda tc: tc.date)deftest_demo(tc):
    # Do something in here with tc.date and tc.datapass

Output:

migration.py::test_demo[2017.01] PASSED                                                                                       
migration.py::test_demo[2017.02] PASSED 

Post a Comment for "Pytest Parameterized Test With Custom Id Function"