diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 76fccb4a18d..1e6a5ffce4c 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1181,19 +1181,25 @@ def _idval( if hook_id: return hook_id + modified_val = None # empty strings are valid as val if isinstance(val, STRING_TYPES): - return _ascii_escaped_by_config(val, config) + modified_val = _ascii_escaped_by_config(val, config) elif val is None or isinstance(val, (float, int, bool)): - return str(val) + modified_val = str(val) elif isinstance(val, REGEX_TYPE): - return ascii_escaped(val.pattern) + modified_val = ascii_escaped(val.pattern) elif isinstance(val, enum.Enum): - return str(val) + modified_val = str(val) elif isinstance(getattr(val, "__name__", None), str): # name of a class, function, module, etc. - name = getattr(val, "__name__") # type: str - return name - return str(argname) + str(idx) + modified_val = getattr(val, "__name__") + + # val does not always enter the isinstance checks due to its type + # when it does we will check the string length returned and use auto generation of ids when over 100 chars + # on types which do not match isinstance checks pytest uses auto generate of ids automatically anyway + if modified_val is None or len(modified_val) > 100: + return str(argname) + str(idx) + return modified_val def _idvalset( diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 4d41910982b..a8cb4fb5eca 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -286,9 +286,8 @@ def test_unicode_idval(self) -> None: ("ação", "a\\xe7\\xe3o"), ("josé@blah.com", "jos\\xe9@blah.com"), ( - "δοκ.ιμή@παράδειγμα.δοκιμή", - "\\u03b4\\u03bf\\u03ba.\\u03b9\\u03bc\\u03ae@\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3" - "\\u03bc\\u03b1.\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae", + "δοκ.ιμή@δοκιμή", + "\\u03b4\\u03bf\\u03ba.\\u03b9\\u03bc\\u03ae@\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae", ), ] for val, expected in values: @@ -1899,3 +1898,38 @@ def test_converted_to_str(a, b): "*= 6 passed in *", ] ) + + +def test_auto_generated_long_parametrized_ids(testdir): + testdir.makepyfile( + """ + import pytest + from datetime import datetime + from enum import Enum + + class CustomEnum(Enum): + OVER = "over" * 26 + UNDER = "under" * 2 + + @pytest.mark.parametrize( + "value, expected", + [ + ("*" * 101, True), + (b"*" * 101, True), + (25, False), + (50.25, False), + ("*" * 50, False), + (True, False), + (datetime(2001, 12, 12), True), + (CustomEnum.OVER, False), + (datetime, False), + (dir, False), + ]) + def test_parametrized_auto_generating_long(request, value, expected): + node_name = request.node.name + was_rewritten = "value" in node_name + assert was_rewritten == expected + """ + ) + result = testdir.runpytest() + result.assert_outcomes(passed=10)