diff --git a/changelog/13457.improvement.rst b/changelog/13457.improvement.rst new file mode 100644 index 00000000000..3937384b322 --- /dev/null +++ b/changelog/13457.improvement.rst @@ -0,0 +1 @@ +The error message about duplicate parametrization no longer displays an internal stack trace. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 1e085a80529..82aab85a300 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1073,13 +1073,16 @@ def setmulti( marks: Iterable[Mark | MarkDecorator], scope: Scope, param_index: int, + nodeid: str, ) -> CallSpec2: params = self.params.copy() indices = self.indices.copy() arg2scope = dict(self._arg2scope) for arg, val in zip(argnames, valset): if arg in params: - raise ValueError(f"duplicate parametrization of {arg!r}") + raise nodes.Collector.CollectError( + f"{nodeid}: duplicate parametrization of {arg!r}" + ) params[arg] = val indices[arg] = param_index arg2scope[arg] = scope @@ -1233,6 +1236,8 @@ def parametrize( It will also override any fixture-function defined scope, allowing to set a dynamic scope using test context or configuration. """ + nodeid = self.definition.nodeid + argnames, parametersets = ParameterSet._for_parametrize( argnames, argvalues, @@ -1244,7 +1249,7 @@ def parametrize( if "request" in argnames: fail( - "'request' is a reserved name and cannot be used in @pytest.mark.parametrize", + f"{nodeid}: 'request' is a reserved name and cannot be used in @pytest.mark.parametrize", pytrace=False, ) @@ -1339,6 +1344,7 @@ def parametrize( marks=param_set.marks, scope=scope_, param_index=param_index, + nodeid=nodeid, ) newcalls.append(newcallspec) self._calls = newcalls diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index e8b345aecc6..7ae26de3a18 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -82,11 +82,15 @@ def func(x, y): metafunc = self.Metafunc(func) metafunc.parametrize("x", [1, 2]) - pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6])) - pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6])) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("x", [5, 6]) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("x", [5, 6]) metafunc.parametrize("y", [1, 2]) - pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6])) - pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6])) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("y", [5, 6]) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("y", [5, 6]) with pytest.raises(TypeError, match="^ids must be a callable or an iterable$"): metafunc.parametrize("y", [5, 6], ids=42) # type: ignore[arg-type]