Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ Hugo van Kemenade
Hui Wang (coldnight)
Ian Bicking
Ian Lesperance
Ilia Sorokin
Ilya Abdolmanafi
Ilya Konstantinov
Ionuț Turturică
Expand Down
1 change: 1 addition & 0 deletions changelog/14619.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improved ``parametrize`` collection errors for tuple-style parameter names with invalid scalar values.
28 changes: 24 additions & 4 deletions src/_pytest/mark/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,28 @@ 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):
for i, param in enumerate(parameters):
try:
values_len = len(param.values)
except TypeError:
values_len = None

if values_len is None:
msg = (
'{nodeid}: in "parametrize" the parameter set at index {index} '
"needs to be a sequence, but got {values!r}"
)
fail(
msg.format(nodeid=nodeid, index=i, values=param.values),
pytrace=False,
)

if values_len != len(argnames):
values = (
list(param.values)
if isinstance(param.values, str)
else param.values
)
msg = (
'{nodeid}: in "parametrize" the number of names ({names_len}):\n'
" {names}\n"
Expand All @@ -224,10 +244,10 @@ def _for_parametrize(
fail(
msg.format(
nodeid=nodeid,
values=param.values,
values=values,
names=argnames,
names_len=len(argnames),
values_len=len(param.values),
values_len=values_len,
),
pytrace=False,
)
Expand Down
30 changes: 30 additions & 0 deletions testing/python/metafunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,36 @@ def func(arg):
assert metafunc._calls[0].params == {"arg": "a"}
assert metafunc._calls[1].params == {"arg": "b"}

def test_parametrize_trailing_comma_scalar_parameter_set(self) -> None:
def func(arg):
pass # pragma: no cover

metafunc = self.Metafunc(func)

with pytest.raises(fail.Exception) as excinfo:
metafunc.parametrize("arg,", [None])

assert str(excinfo.value) == (
'mock::nodeid: in "parametrize" the parameter set at index 0 '
"needs to be a sequence, but got None"
)

def test_parametrize_string_parameter_set_error_shows_sequence(self) -> None:
def func(arg):
pass # pragma: no cover

metafunc = self.Metafunc(func)

with pytest.raises(fail.Exception) as excinfo:
metafunc.parametrize("arg,", ["foo"])

assert str(excinfo.value) == (
'mock::nodeid: in "parametrize" the number of names (1):\n'
" ['arg']\n"
"must be equal to the number of values (3):\n"
" ['f', 'o', 'o']"
)

def test_parametrize_error(self) -> None:
def func(x, y):
pass
Expand Down
Loading