Skip to content

Commit 49a127a

Browse files
committed
Handle missing terminalreporter in get_terminal_writer
1 parent 91e5af1 commit 49a127a

3 files changed

Lines changed: 63 additions & 2 deletions

File tree

changelog/14377.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed :meth:`Config.get_terminal_writer() <pytest.Config.get_terminal_writer>` to fall back gracefully when the ``terminalreporter`` plugin has been unregistered, avoiding an internal ``AssertionError`` in plugin setups that still need assertion rendering.

src/_pytest/config/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,8 +1175,9 @@ def get_terminal_writer(self) -> TerminalWriter:
11751175
terminalreporter: TerminalReporter | None = self.pluginmanager.get_plugin(
11761176
"terminalreporter"
11771177
)
1178-
assert terminalreporter is not None
1179-
return terminalreporter._tw
1178+
if terminalreporter is not None:
1179+
return terminalreporter._tw
1180+
return create_terminal_writer(self)
11801181

11811182
def pytest_cmdline_parse(
11821183
self, pluginmanager: PytestPluginManager, args: list[str]

testing/test_config.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from typing import Any
1414

1515
import _pytest._code
16+
from _pytest._io import TerminalWriter
1617
from _pytest.config import _get_plugin_specs_as_list
1718
from _pytest.config import _iter_rewritable_modules
1819
from _pytest.config import _strtobool
@@ -1719,6 +1720,64 @@ def pytest_sessionstart(session):
17191720
assert result.ret == 0
17201721

17211722

1723+
def test_get_terminal_writer_falls_back_without_terminalreporter(
1724+
pytester: Pytester,
1725+
) -> None:
1726+
config = pytester.parseconfigure("--color=no", "--code-highlight=no")
1727+
terminalreporter = config.pluginmanager.get_plugin("terminalreporter")
1728+
assert terminalreporter is not None
1729+
1730+
config.pluginmanager.unregister(terminalreporter)
1731+
1732+
writer = config.get_terminal_writer()
1733+
assert isinstance(writer, TerminalWriter)
1734+
assert writer.hasmarkup is False
1735+
assert writer.code_highlight is False
1736+
1737+
1738+
def test_assertion_rewriting_works_without_terminalreporter(
1739+
pytester: Pytester,
1740+
) -> None:
1741+
pytester.makeconftest(
1742+
"""
1743+
import pathlib
1744+
import pytest
1745+
1746+
@pytest.hookimpl(trylast=True)
1747+
def pytest_configure(config):
1748+
reporter = config.pluginmanager.get_plugin("terminalreporter")
1749+
assert reporter is not None
1750+
config.pluginmanager.unregister(reporter)
1751+
1752+
def pytest_runtest_logreport(report):
1753+
if report.when == "call" and report.failed:
1754+
pathlib.Path("report.txt").write_text(
1755+
str(report.longrepr), encoding="utf-8"
1756+
)
1757+
"""
1758+
)
1759+
pytester.makepyfile(
1760+
helper="""
1761+
def run():
1762+
assert "actual" == "expected"
1763+
""",
1764+
test_foo="""
1765+
from helper import run
1766+
1767+
def test_foo():
1768+
run()
1769+
""",
1770+
)
1771+
1772+
result = pytester.runpytest()
1773+
assert result.ret == ExitCode.TESTS_FAILED
1774+
1775+
report = pytester.path.joinpath("report.txt").read_text(encoding="utf-8")
1776+
assert '"actual" == "expected"' in report
1777+
assert "helper.py:2: AssertionError" in report
1778+
assert "terminalreporter is not None" not in report
1779+
1780+
17221781
def test_invalid_options_show_extra_information(pytester: Pytester) -> None:
17231782
"""Display extra information when pytest exits due to unrecognized
17241783
options in the command-line."""

0 commit comments

Comments
 (0)