From f35bed25545376b663a74ff935be2e1b0e93e9f2 Mon Sep 17 00:00:00 2001 From: marko1olo Date: Fri, 5 Jun 2026 22:10:42 +0400 Subject: [PATCH 1/2] Document assertrepr compare with pass hook --- src/_pytest/hookspec.py | 7 ++++++- testing/test_assertrewrite.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 6c5dd4b7c4a..a4bec917884 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -934,7 +934,12 @@ def pytest_unconfigure(config: Config) -> None: def pytest_assertrepr_compare( config: Config, op: str, left: object, right: object ) -> list[str] | None: - """Return explanation for comparisons in failing assert expressions. + """Return explanation for comparisons in assert expressions. + + By default, this hook is used only for failing assertions. It can also + be called for passing assertions when the :confval:`enable_assertion_pass_hook` + option is enabled and a :hook:`pytest_assertion_pass` hook implementation is + active, because pytest needs an assertion explanation to pass to that hook. Return None for no custom explanation, otherwise return a list of strings. The strings will be joined by newlines but any newlines diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index e11863547ba..d938bfd7e9e 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2072,6 +2072,39 @@ def test(): result = pytester.runpytest() result.stdout.fnmatch_lines("*Assertion Passed: f() 1") + def test_assertrepr_compare_called_for_pass_hook( + self, pytester: Pytester, flag_on + ) -> None: + pytester.makeconftest( + """\ + def pytest_assertrepr_compare(config, op, left, right): + config.rootpath.joinpath("reprcompare.txt").write_text( + f"{op}:{left}:{right}", encoding="utf-8" + ) + return ["custom pass comparison"] + + def pytest_assertion_pass(item, lineno, orig, expl): + item.config.rootpath.joinpath("assertion-pass.txt").write_text( + expl, encoding="utf-8" + ) + """ + ) + pytester.makepyfile( + """\ + def test_simple(): + assert 1 == 1 + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=1) + assert pytester.path.joinpath("reprcompare.txt").read_text( + encoding="utf-8" + ) == "==:1:1" + assert ( + pytester.path.joinpath("assertion-pass.txt").read_text(encoding="utf-8") + == "custom pass comparison" + ) + def test_hook_not_called_without_hookimpl( self, pytester: Pytester, monkeypatch, flag_on ) -> None: From 8f33bd0e404492812f0f55fdd57355d198f03aef Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 18:15:46 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- testing/test_assertrewrite.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index d938bfd7e9e..75e4a71551d 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2097,9 +2097,10 @@ def test_simple(): ) result = pytester.runpytest() result.assert_outcomes(passed=1) - assert pytester.path.joinpath("reprcompare.txt").read_text( - encoding="utf-8" - ) == "==:1:1" + assert ( + pytester.path.joinpath("reprcompare.txt").read_text(encoding="utf-8") + == "==:1:1" + ) assert ( pytester.path.joinpath("assertion-pass.txt").read_text(encoding="utf-8") == "custom pass comparison"