diff --git a/changelog/4739.bugfix.rst b/changelog/4739.bugfix.rst new file mode 100644 index 000000000..dcd44d3fa --- /dev/null +++ b/changelog/4739.bugfix.rst @@ -0,0 +1 @@ +Fix ``parametrize(... ids=)`` when the function returns non-strings. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 85373f47c..aaa49f7dd 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1144,9 +1144,10 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect): def _idval(val, argname, idx, idfn, item, config): if idfn: - s = None try: - s = idfn(val) + generated_id = idfn(val) + if generated_id is not None: + val = generated_id except Exception as e: # See issue https://github.com/pytest-dev/pytest/issues/2169 msg = "{}: error raised while trying to determine id of parameter '{}' at position {}\n" @@ -1154,10 +1155,7 @@ def _idval(val, argname, idx, idfn, item, config): # we only append the exception type and message because on Python 2 reraise does nothing msg += " {}: {}\n".format(type(e).__name__, e) six.raise_from(ValueError(msg), e) - if s: - return ascii_escaped(s) - - if config: + elif config: hook_id = config.hook.pytest_make_parametrize_id( config=config, val=val, argname=argname ) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 5c352efd1..fa22966d8 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -418,6 +418,21 @@ class TestMetafunc(object): ] ) + def test_parametrize_ids_returns_non_string(self, testdir): + testdir.makepyfile( + """\ + import pytest + + def ids(d): + return d + + @pytest.mark.parametrize("arg", ({1: 2}, {3, 4}), ids=ids) + def test(arg): + assert arg + """ + ) + assert testdir.runpytest().ret == 0 + def test_idmaker_with_ids(self): from _pytest.python import idmaker