Use NamedTuple for pytest_report_teststatus return value (#10972)

Closes #10872

---------

Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
This commit is contained in:
Roberto Aldera 2023-05-19 13:24:28 +02:00 committed by GitHub
parent ba32a3bd87
commit 9fa82598a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 5 deletions

View File

@ -308,6 +308,7 @@ Rafal Semik
Raquel Alegre Raquel Alegre
Ravi Chandra Ravi Chandra
Robert Holt Robert Holt
Roberto Aldera
Roberto Polli Roberto Polli
Roland Puntaier Roland Puntaier
Romain Dorgueil Romain Dorgueil

View File

@ -0,0 +1 @@
Update test log report annotation to named tuple and fixed inconsistency in docs for :hook:`pytest_report_teststatus` hook.

View File

@ -956,6 +956,12 @@ TestReport
:show-inheritance: :show-inheritance:
:inherited-members: :inherited-members:
TestShortLogReport
~~~~~~~~~~~~~~~~~~
.. autoclass:: pytest.TestShortLogReport()
:members:
_Result _Result
~~~~~~~ ~~~~~~~

View File

@ -41,6 +41,7 @@ if TYPE_CHECKING:
from _pytest.reports import TestReport from _pytest.reports import TestReport
from _pytest.runner import CallInfo from _pytest.runner import CallInfo
from _pytest.terminal import TerminalReporter from _pytest.terminal import TerminalReporter
from _pytest.terminal import TestShortLogReport
from _pytest.compat import LEGACY_PATH from _pytest.compat import LEGACY_PATH
@ -806,7 +807,7 @@ def pytest_report_collectionfinish( # type:ignore[empty-body]
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_report_teststatus( # type:ignore[empty-body] def pytest_report_teststatus( # type:ignore[empty-body]
report: Union["CollectReport", "TestReport"], config: "Config" report: Union["CollectReport", "TestReport"], config: "Config"
) -> Tuple[str, str, Union[str, Mapping[str, bool]]]: ) -> "TestShortLogReport | Tuple[str, str, Union[str, Tuple[str, Mapping[str, bool]]]]":
"""Return result-category, shortletter and verbose word for status """Return result-category, shortletter and verbose word for status
reporting. reporting.

View File

@ -21,6 +21,7 @@ from typing import Dict
from typing import Generator from typing import Generator
from typing import List from typing import List
from typing import Mapping from typing import Mapping
from typing import NamedTuple
from typing import Optional from typing import Optional
from typing import Sequence from typing import Sequence
from typing import Set from typing import Set
@ -112,6 +113,26 @@ class MoreQuietAction(argparse.Action):
namespace.quiet = getattr(namespace, "quiet", 0) + 1 namespace.quiet = getattr(namespace, "quiet", 0) + 1
class TestShortLogReport(NamedTuple):
"""Used to store the test status result category, shortletter and verbose word.
For example ``"rerun", "R", ("RERUN", {"yellow": True})``.
:ivar category:
The class of result, for example ``passed``, ``skipped``, ``error``, or the empty string.
:ivar letter:
The short letter shown as testing progresses, for example ``"."``, ``"s"``, ``"E"``, or the empty string.
:ivar word:
Verbose word is shown as testing progresses in verbose mode, for example ``"PASSED"``, ``"SKIPPED"``,
``"ERROR"``, or the empty string.
"""
category: str
letter: str
word: Union[str, Tuple[str, Mapping[str, bool]]]
def pytest_addoption(parser: Parser) -> None: def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("terminal reporting", "Reporting", after="general") group = parser.getgroup("terminal reporting", "Reporting", after="general")
group._addoption( group._addoption(
@ -548,10 +569,11 @@ class TerminalReporter:
def pytest_runtest_logreport(self, report: TestReport) -> None: def pytest_runtest_logreport(self, report: TestReport) -> None:
self._tests_ran = True self._tests_ran = True
rep = report rep = report
res: Tuple[
str, str, Union[str, Tuple[str, Mapping[str, bool]]] res = TestShortLogReport(
] = self.config.hook.pytest_report_teststatus(report=rep, config=self.config) *self.config.hook.pytest_report_teststatus(report=rep, config=self.config)
category, letter, word = res )
category, letter, word = res.category, res.letter, res.word
if not isinstance(word, tuple): if not isinstance(word, tuple):
markup = None markup = None
else: else:

View File

@ -62,6 +62,7 @@ from _pytest.reports import TestReport
from _pytest.runner import CallInfo from _pytest.runner import CallInfo
from _pytest.stash import Stash from _pytest.stash import Stash
from _pytest.stash import StashKey from _pytest.stash import StashKey
from _pytest.terminal import TestShortLogReport
from _pytest.tmpdir import TempPathFactory from _pytest.tmpdir import TempPathFactory
from _pytest.warning_types import PytestAssertRewriteWarning from _pytest.warning_types import PytestAssertRewriteWarning
from _pytest.warning_types import PytestCacheWarning from _pytest.warning_types import PytestCacheWarning
@ -152,6 +153,7 @@ __all__ = [
"TempPathFactory", "TempPathFactory",
"Testdir", "Testdir",
"TestReport", "TestReport",
"TestShortLogReport",
"UsageError", "UsageError",
"WarningsRecorder", "WarningsRecorder",
"warns", "warns",