Skip to content

Commit

Permalink
fix #13031: use the concrete id NOTSET for the empty parameter list (#…
Browse files Browse the repository at this point in the history
…13073)

* fix #13031: use the concrete id NOTSET for the empty parameter list stand-in

this ensures we dont invoke idfunc with the internal NOTSET enum token

* Apply suggestions from code review

Co-authored-by: Bruno Oliveira <[email protected]>

---------

Co-authored-by: Bruno Oliveira <[email protected]>
  • Loading branch information
RonnyPfannschmidt and nicoddemus authored Dec 21, 2024
1 parent 868e1d2 commit 7d585ac
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog/13031.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
An empty parameter set as in ``pytest.mark.parametrize([], ids=idfunc)`` will no longer trigger a call to ``idfunc`` with internal objects.
12 changes: 7 additions & 5 deletions src/_pytest/mark/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,18 @@ def get_empty_parameterset_mark(
) -> MarkDecorator:
from ..nodes import Collector

argslisting = ", ".join(argnames)

fs, lineno = getfslineno(func)
reason = f"got empty parameter set {argnames!r}, function {func.__name__} at {fs}:{lineno}"
reason = f"got empty parameter set for ({argslisting})"
requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION)
if requested_mark in ("", None, "skip"):
mark = MARK_GEN.skip(reason=reason)
elif requested_mark == "xfail":
mark = MARK_GEN.xfail(reason=reason, run=False)
elif requested_mark == "fail_at_collect":
f_name = func.__name__
_, lineno = getfslineno(func)
raise Collector.CollectError(
f"Empty parameter set in '{f_name}' at line {lineno + 1}"
f"Empty parameter set in '{func.__name__}' at line {lineno + 1}"
)
else:
raise LookupError(requested_mark)
Expand Down Expand Up @@ -181,7 +181,9 @@ def _for_parametrize(
# parameter set with NOTSET values, with the "empty parameter set" mark applied to it.
mark = get_empty_parameterset_mark(config, argnames, func)
parameters.append(
ParameterSet(values=(NOTSET,) * len(argnames), marks=[mark], id=None)
ParameterSet(
values=(NOTSET,) * len(argnames), marks=[mark], id="NOTSET"
)
)
return argnames, parameters

Expand Down
26 changes: 26 additions & 0 deletions testing/test_mark.py
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,32 @@ def test():
assert result.ret == ExitCode.INTERRUPTED


def test_paramset_empty_no_idfunc(
pytester: Pytester, monkeypatch: pytest.MonkeyPatch
) -> None:
"""An empty parameter set should not call the user provided id function (#13031)."""
p1 = pytester.makepyfile(
"""
import pytest
def idfunc(value):
raise ValueError()
@pytest.mark.parametrize("param", [], ids=idfunc)
def test(param):
pass
"""
)
result = pytester.runpytest(p1, "-v", "-rs")
result.stdout.fnmatch_lines(
[
"* collected 1 item",
"test_paramset_empty_no_idfunc* SKIPPED *",
"SKIPPED [1] test_paramset_empty_no_idfunc.py:5: got empty parameter set for (param)",
"*= 1 skipped in *",
]
)


def test_parameterset_for_parametrize_bad_markname(pytester: Pytester) -> None:
with pytest.raises(pytest.UsageError):
test_parameterset_for_parametrize_marks(pytester, "bad")
Expand Down

0 comments on commit 7d585ac

Please sign in to comment.