Pytest: Send parameters in parametrize as dict to `ids=` callable

Created on 28 Jun 2018  路  3Comments  路  Source: pytest-dev/pytest

Hello,

Is there a way to get all the parameters for parametrize inside a dict and sent to a ids= callable?

I would like to do something like:

@pytest.mark.parametrize("a, b, c",
[
  (1518, 200, 3600),
  (67, 10, 3600)
],
ids=(lambda p: 'Frame size: {a}B, Rate: {b}Mbit/s, Duration: {c}s'.format(**p)))
def test_case_one(a, b, c):
...

So I'd get the output:

test_case_one[Frame size: 1518B, Rate: 200Mbit/s, Duration: 3600s] FAILED
...
test_case_one[Frame size: 67B, Rate: 10Mbit/s, Duration: 3600s] PASSED
...

But as the ids= callable is called for every value it's hard to identify what each value is when they're integers.

One solution would be to use only one dict parameter, but then I would need to rewrite lot of tests...

Thanks :)

question

Most helpful comment

@willeponken consider adding a wrapper for parametrize, e.g.

def my_parametrize(argname, argvalues, indirect=False, ids=None, scope=None):
    if not ids:
        argnames = argname.split(',') if isinstance(argname, str) else argname
        ids = [
            ','.join(f'{k}={v}' for k, v in zip(argnames, p_argvalues))
            for p_argvalues in argvalues
        ]
    return pytest.mark.parametrize(argname, argvalues,
                                   indirect=indirect,
                                   ids=ids,
                                   scope=scope)

@my_parametrize('a,b,c', [(1, 2, 3), (4, 5, 6), (7, 8, 9)])
def test_foo(a, b, c):
    assert False

This will produce test IDs like test_foo[a=1,b=2,c=3].

All 3 comments

GitMate.io thinks possibly related issues are https://github.com/pytest-dev/pytest/issues/2272 (Question: Can callable as argument to ids parameter of parametrize of operate on a tuple?), https://github.com/pytest-dev/pytest/issues/2176 (parametrize ignores marks if parameters are symbols), https://github.com/pytest-dev/pytest/issues/1104 (UnicodeEncodeError with unicode parameters in mark.parametrize), https://github.com/pytest-dev/pytest/issues/570 (indirect=True in parametrize breaks fixture scopes), and https://github.com/pytest-dev/pytest/issues/2853 ("parametrize" misspelled).

@willeponken consider adding a wrapper for parametrize, e.g.

def my_parametrize(argname, argvalues, indirect=False, ids=None, scope=None):
    if not ids:
        argnames = argname.split(',') if isinstance(argname, str) else argname
        ids = [
            ','.join(f'{k}={v}' for k, v in zip(argnames, p_argvalues))
            for p_argvalues in argvalues
        ]
    return pytest.mark.parametrize(argname, argvalues,
                                   indirect=indirect,
                                   ids=ids,
                                   scope=scope)

@my_parametrize('a,b,c', [(1, 2, 3), (4, 5, 6), (7, 8, 9)])
def test_foo(a, b, c):
    assert False

This will produce test IDs like test_foo[a=1,b=2,c=3].

Aha! Exactly what I wanted, thank you :+1:

Was this page helpful?
0 / 5 - 0 ratings