diff --git a/changelog/14377.bugfix.rst b/changelog/14377.bugfix.rst new file mode 100644 index 00000000000..5d94fed0f54 --- /dev/null +++ b/changelog/14377.bugfix.rst @@ -0,0 +1 @@ +Fixed crash in `Config.get_terminal_writer` when an assertion fails with the ``terminalreporter`` plugin disabled. diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index 22f3ca8e258..4b946bc7074 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -205,4 +205,15 @@ def pytest_sessionfinish(session: Session) -> None: def pytest_assertrepr_compare( config: Config, op: str, left: Any, right: Any ) -> list[str] | None: - return util.assertrepr_compare(config=config, op=op, left=left, right=right) + if config.pluginmanager.has_plugin("terminalreporter"): + highlighter = config.get_terminal_writer()._highlight + else: + # Keep it plaintext when not using terminalrepoterer (#14377). + highlighter = util.dummy_highlighter + return util.assertrepr_compare( + op=op, + left=left, + right=right, + verbose=config.get_verbosity(Config.VERBOSITY_ASSERTIONS), + highlighter=highlighter, + ) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 5d5e6d4777d..07918a66284 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -174,11 +174,14 @@ def has_default_eq(obj: object) -> bool: def assertrepr_compare( - config: Config, op: str, left: object, right: object + op: str, + left: object, + right: object, + *, + verbose: int, + highlighter: _HighlightFunc, ) -> list[str] | None: """Return specialised explanations for some operators/operands.""" - verbose = config.get_verbosity(Config.VERBOSITY_ASSERTIONS) - # Strings which normalize equal are often hard to distinguish when printed; use ascii() to make this easier. # See issue #3246. use_ascii = ( @@ -201,7 +204,6 @@ def assertrepr_compare( right_repr = saferepr(right, maxsize=maxsize, use_ascii=use_ascii) summary = f"{left_repr} {op} {right_repr}" - highlighter = config.get_terminal_writer()._highlight explanation = None try: diff --git a/testing/test_assertion.py b/testing/test_assertion.py index d68fd0b1fba..9a7305a2905 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -24,7 +24,13 @@ class TerminalWriter: def _highlight(self, source, lexer="python"): return source + class PluginManager: + def has_plugin(self, name: str) -> bool: + return True + class Config: + pluginmanager = PluginManager() + def get_terminal_writer(self): return TerminalWriter() diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 92664354470..2668001af65 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2404,3 +2404,22 @@ def test_saferepr_unbounded(self): _saferepr(self.Help) == f"" ) + + +def test_assertion_failure_when_terminalreporter_is_disabled( + pytester: Pytester, +) -> None: + """Assertion rewriting doesn't crash when the terminalreporter plugin is + disabled (#14378).""" + pytester.makepyfile( + """ + import pytest + + def test(): + with pytest.raises(AssertionError) as excinfo: + assert 0 == 1 + assert excinfo.value.args[0] == 'assert 0 == 1' + """ + ) + reprec = pytester.inline_run("-p", "no:terminalreporter") + reprec.assertoutcome(passed=1)