diff --git a/AUTHORS b/AUTHORS index 972f39aa45e..94a70b16a2e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -333,6 +333,7 @@ Mihail Milushev Mike Fiedler (miketheman) Mike Hoyle (hoylemd) Mike Lundy +Mike Ma Milan Lesnek minbang930 Miro HronĨok diff --git a/changelog/14619.bugfix.rst b/changelog/14619.bugfix.rst new file mode 100644 index 00000000000..6208677f843 --- /dev/null +++ b/changelog/14619.bugfix.rst @@ -0,0 +1 @@ +Fixed a crash in :func:`pytest.mark.parametrize` when a non-sequence value is passed for a parameter set. It now provides a clear error message during collection. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 5449b17a1c6..546e258139b 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -214,7 +214,17 @@ def _for_parametrize( if parameters: # Check all parameter sets have the correct number of values. for param in parameters: - if len(param.values) != len(argnames): + try: + values_len = len(param.values) + except TypeError: + values_len = None + if values_len is None: + fail( + f'{nodeid}: in "parametrize" expected a sequence of values, got {type(param.values).__name__}:\n' + f" {param.values}", + pytrace=False, + ) + if values_len != len(argnames): msg = ( '{nodeid}: in "parametrize" the number of names ({names_len}):\n' " {names}\n" @@ -227,7 +237,7 @@ def _for_parametrize( values=param.values, names=argnames, names_len=len(argnames), - values_len=len(param.values), + values_len=values_len, ), pytrace=False, ) diff --git a/testing/test_mark.py b/testing/test_mark.py index 253cda94503..5c8b9f9f967 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -495,6 +495,28 @@ def test_func(foo, bar): ) +def test_parametrized_collect_with_non_sequence_values(pytester: Pytester) -> None: + """Test collect parametrized func with tuple-style argnames and scalar values.""" + py_file = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("x,", [None]) + def test_func(x): + pass + """ + ) + + result = pytester.runpytest(py_file) + result.stdout.fnmatch_lines( + [ + "test_parametrized_collect_with_non_sequence_values.py::test_func: " + 'in "parametrize" expected a sequence of values, got NoneType:', + " None", + ] + ) + + def test_parametrized_with_kwargs(pytester: Pytester) -> None: """Test collect parametrized func with wrong number of args.""" py_file = pytester.makepyfile(