Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions changelog/14377.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed crash in `Config.get_terminal_writer` when an assertion fails with the ``terminalreporter`` plugin disabled.
13 changes: 12 additions & 1 deletion src/_pytest/assertion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
10 changes: 6 additions & 4 deletions src/_pytest/assertion/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
Expand All @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions testing/test_assertion.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
19 changes: 19 additions & 0 deletions testing/test_assertrewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -2404,3 +2404,22 @@ def test_saferepr_unbounded(self):
_saferepr(self.Help)
== f"<class '{Path(__file__).stem}.{self.__class__.__name__}.Help'>"
)


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)