Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more parameters to overridable methods for parameterized ID creation #12628

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0d7270e
Add idx to hook callback
Jul 18, 2024
d847ccb
Add argname and idx to ID callable arguments
Jul 18, 2024
591c2b4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
1e9c984
Fixed idfn type hints
Jul 18, 2024
d7ce6ae
Merge branch 'add-new-parameters-to-overridable-methods' of https://g…
Jul 18, 2024
87950b6
Fixed test methods
Jul 18, 2024
a8693d2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
a778e57
Added changelog item
Jul 18, 2024
119a7e5
Merge branch 'add-new-parameters-to-overridable-methods' of https://g…
Jul 18, 2024
103d2bd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
c700976
Fixed parameter type in IdMaker instance creation
Jul 18, 2024
5ceb849
Merge branch 'add-new-parameters-to-overridable-methods' of https://g…
Jul 18, 2024
929949f
Fixed parameter type
Jul 18, 2024
a698b94
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
10603cd
Fixed fixture type hint
Jul 18, 2024
5d2d1c6
Merge branch 'add-new-parameters-to-overridable-methods' of https://g…
Jul 18, 2024
9b329f0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
024e7bd
Fixed type hint and argument number
Jul 18, 2024
23f0f41
Merge branch 'add-new-parameters-to-overridable-methods' of https://g…
Jul 18, 2024
441fad4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
0f3ec5b
Fixed more type hints
Jul 18, 2024
408d7be
Merge branch 'add-new-parameters-to-overridable-methods' of https://g…
Jul 18, 2024
a2e1868
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
9e0de13
Fixing types and typehints
Jul 18, 2024
f25907f
Merge branch 'add-new-parameters-to-overridable-methods' of https://g…
Jul 18, 2024
07ff3b3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 18, 2024
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
3 changes: 3 additions & 0 deletions changelog/12628.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Existing parameters (argname and case index) are passed to hook and idfn for parameterized test ID creation.

-- by :user:`nicoloborghi`
24 changes: 18 additions & 6 deletions src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,9 @@ def __init__(
func: _FixtureFunc[FixtureValue],
scope: Scope | _ScopeName | Callable[[str, Config], _ScopeName] | None,
params: Sequence[object] | None,
ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None,
ids: tuple[object | None, ...]
| Callable[[Any, str, int], object | None]
| None = None,
*,
_ispytest: bool = False,
) -> None:
Expand Down Expand Up @@ -1180,7 +1182,9 @@ class FixtureFunctionMarker:
scope: _ScopeName | Callable[[str, Config], _ScopeName]
params: tuple[object, ...] | None
autouse: bool = False
ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None
ids: tuple[object | None, ...] | Callable[[Any, str, int], object | None] | None = (
None
)
name: str | None = None

_ispytest: dataclasses.InitVar[bool] = False
Expand Down Expand Up @@ -1222,7 +1226,9 @@ def fixture(
scope: _ScopeName | Callable[[str, Config], _ScopeName] = ...,
params: Iterable[object] | None = ...,
autouse: bool = ...,
ids: Sequence[object | None] | Callable[[Any], object | None] | None = ...,
ids: Sequence[object | None]
| Callable[[Any, str, int], object | None]
| None = ...,
name: str | None = ...,
) -> FixtureFunction: ...

Expand All @@ -1234,7 +1240,9 @@ def fixture(
scope: _ScopeName | Callable[[str, Config], _ScopeName] = ...,
params: Iterable[object] | None = ...,
autouse: bool = ...,
ids: Sequence[object | None] | Callable[[Any], object | None] | None = ...,
ids: Sequence[object | None]
| Callable[[Any, str, int], object | None]
| None = ...,
name: str | None = None,
) -> FixtureFunctionMarker: ...

Expand All @@ -1245,7 +1253,9 @@ def fixture(
scope: _ScopeName | Callable[[str, Config], _ScopeName] = "function",
params: Iterable[object] | None = None,
autouse: bool = False,
ids: Sequence[object | None] | Callable[[Any], object | None] | None = None,
ids: Sequence[object | None]
| Callable[[Any, str, int], object | None]
| None = None,
name: str | None = None,
) -> FixtureFunctionMarker | FixtureFunction:
"""Decorator to mark a fixture factory function.
Expand Down Expand Up @@ -1633,7 +1643,9 @@ def _register_fixture(
nodeid: str | None,
scope: Scope | _ScopeName | Callable[[str, Config], _ScopeName] = "function",
params: Sequence[object] | None = None,
ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None,
ids: tuple[object | None, ...]
| Callable[[Any, str, int], object | None]
| None = None,
autouse: bool = False,
) -> None:
"""Register a fixture
Expand Down
5 changes: 4 additions & 1 deletion src/_pytest/hookspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,9 @@ def pytest_generate_tests(metafunc: Metafunc) -> None:


@hookspec(firstresult=True)
def pytest_make_parametrize_id(config: Config, val: object, argname: str) -> str | None:
def pytest_make_parametrize_id(
config: Config, val: object, argname: str, idx: int
) -> str | None:
"""Return a user-friendly string representation of the given ``val``
that will be used by @pytest.mark.parametrize calls, or None if the hook
doesn't know about ``val``.
Expand All @@ -600,6 +602,7 @@ def pytest_make_parametrize_id(config: Config, val: object, argname: str) -> str
:param config: The pytest config object.
:param val: The parametrized value.
:param argname: The automatic parameter name produced by pytest.
:param idx: The iteration number of parameterized tests as calculated by pytest.

Use in conftest plugins
=======================
Expand Down
16 changes: 9 additions & 7 deletions src/_pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@
parametersets: Sequence[ParameterSet]
# Optionally, a user-provided callable to make IDs for parameters in a
# ParameterSet.
idfn: Callable[[Any], object | None] | None
idfn: Callable[[Any, str, int], object | None] | None
# Optionally, explicit IDs for ParameterSets by index.
ids: Sequence[object | None] | None
# Optionally, the pytest config.
Expand Down Expand Up @@ -939,7 +939,7 @@
idval = self._idval_from_function(val, argname, idx)
if idval is not None:
return idval
idval = self._idval_from_hook(val, argname)
idval = self._idval_from_hook(val, argname, idx)
if idval is not None:
return idval
idval = self._idval_from_value(val)
Expand All @@ -953,7 +953,7 @@
if self.idfn is None:
return None
try:
id = self.idfn(val)
id = self.idfn(val, argname, idx)

Check warning on line 956 in src/_pytest/python.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python.py#L956

Added line #L956 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change,the old signature needs to be supported as well

I recommend using a callable protocol as starting points

except Exception as e:
prefix = f"{self.nodeid}: " if self.nodeid is not None else ""
msg = "error raised while trying to determine id of parameter '{}' at position {}"
Expand All @@ -963,12 +963,12 @@
return None
return self._idval_from_value(id)

def _idval_from_hook(self, val: object, argname: str) -> str | None:
def _idval_from_hook(self, val: object, argname: str, idx: int) -> str | None:
"""Try to make an ID for a parameter in a ParameterSet by calling the
:hook:`pytest_make_parametrize_id` hook."""
if self.config:
id: str | None = self.config.hook.pytest_make_parametrize_id(
config=self.config, val=val, argname=argname
config=self.config, val=val, argname=argname, idx=idx
)
return id
return None
Expand Down Expand Up @@ -1136,7 +1136,9 @@
argnames: str | Sequence[str],
argvalues: Iterable[ParameterSet | Sequence[object] | object],
indirect: bool | Sequence[str] = False,
ids: Iterable[object | None] | Callable[[Any], object | None] | None = None,
ids: Iterable[object | None]
| Callable[[Any, str, int], object | None]
| None = None,
scope: _ScopeName | None = None,
*,
_param_mark: Mark | None = None,
Expand Down Expand Up @@ -1315,7 +1317,7 @@
def _resolve_parameter_set_ids(
self,
argnames: Sequence[str],
ids: Iterable[object | None] | Callable[[Any], object | None] | None,
ids: Iterable[object | None] | Callable[[Any, str, int], object | None] | None,
parametersets: Sequence[ParameterSet],
nodeid: str,
) -> list[str]:
Expand Down
6 changes: 5 additions & 1 deletion src/_pytest/setuponly.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@
# display it now and during the teardown (in .finish()).
if fixturedef.ids:
if callable(fixturedef.ids):
param = fixturedef.ids(request.param)
param = fixturedef.ids(

Check warning on line 44 in src/_pytest/setuponly.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/setuponly.py#L44

Added line #L44 was not covered by tests
request.param,
request.fixturename or "",
request.param_index,
)
else:
param = fixturedef.ids[request.param_index]
else:
Expand Down
6 changes: 3 additions & 3 deletions testing/python/metafunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ def test_idmaker_enum(self) -> None:
def test_idmaker_idfn(self) -> None:
"""#351"""

def ids(val: object) -> str | None:
def ids(val: object, argname: str, idx: int) -> str | None:
if isinstance(val, Exception):
return repr(val)
return None
Expand All @@ -537,7 +537,7 @@ def ids(val: object) -> str | None:
def test_idmaker_idfn_unique_names(self) -> None:
"""#351"""

def ids(val: object) -> str:
def ids(val: object, argname: str, idx: int) -> str:
return "a"

result = IdMaker(
Expand Down Expand Up @@ -585,7 +585,7 @@ def getini(self, name):
result = IdMaker(
("a",),
[pytest.param("string")],
lambda _: "ação",
lambda _, __, ___: "ação",
None,
config,
None,
Expand Down
10 changes: 9 additions & 1 deletion testing/typing_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from __future__ import annotations

import contextlib
from typing import Any
from typing import Callable
from typing import cast
from typing import Optional

from typing_extensions import assert_type
Expand All @@ -23,7 +26,12 @@ def check_mark_xfail_raises() -> None:


# Issue #7494.
@pytest.fixture(params=[(0, 0), (1, 1)], ids=lambda x: str(x[0]))
@pytest.fixture(
params=[(0, 0), (1, 1)],
ids=cast(
Callable[[Any, str, int], object | None] | None, lambda x, _, __: str(x[0])
),
)
def check_fixture_ids_callable() -> None:
pass

Expand Down
Loading