Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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?

like image 233
Gaurang Shah Avatar asked Aug 25 '17 10:08

Gaurang Shah


People also ask

What is the syntax to run a parameterized test in pytest?

you can put @pytest. mark. parametrize style parametrization on the test functions to parametrize input/output values as well.

How does pytest Parametrize work?

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.


1 Answers

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.

like image 60
kchomski Avatar answered Sep 19 '22 14:09

kchomski