resultlog: add missing type annotations
This commit is contained in:
parent
303030c141
commit
62ddf7a0e5
|
@ -1,5 +1,7 @@
|
||||||
"""log machine-parseable test session result information to a plain text file."""
|
"""log machine-parseable test session result information to a plain text file."""
|
||||||
import os
|
import os
|
||||||
|
from typing import IO
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
@ -52,16 +54,18 @@ def pytest_unconfigure(config: Config) -> None:
|
||||||
|
|
||||||
|
|
||||||
class ResultLog:
|
class ResultLog:
|
||||||
def __init__(self, config, logfile):
|
def __init__(self, config: Config, logfile: IO[str]) -> None:
|
||||||
self.config = config
|
self.config = config
|
||||||
self.logfile = logfile # preferably line buffered
|
self.logfile = logfile # preferably line buffered
|
||||||
|
|
||||||
def write_log_entry(self, testpath, lettercode, longrepr):
|
def write_log_entry(self, testpath: str, lettercode: str, longrepr: str) -> None:
|
||||||
print("{} {}".format(lettercode, testpath), file=self.logfile)
|
print("{} {}".format(lettercode, testpath), file=self.logfile)
|
||||||
for line in longrepr.splitlines():
|
for line in longrepr.splitlines():
|
||||||
print(" %s" % line, file=self.logfile)
|
print(" %s" % line, file=self.logfile)
|
||||||
|
|
||||||
def log_outcome(self, report, lettercode, longrepr):
|
def log_outcome(
|
||||||
|
self, report: Union[TestReport, CollectReport], lettercode: str, longrepr: str
|
||||||
|
) -> None:
|
||||||
testpath = getattr(report, "nodeid", None)
|
testpath = getattr(report, "nodeid", None)
|
||||||
if testpath is None:
|
if testpath is None:
|
||||||
testpath = report.fspath
|
testpath = report.fspath
|
||||||
|
@ -73,7 +77,7 @@ class ResultLog:
|
||||||
res = self.config.hook.pytest_report_teststatus(
|
res = self.config.hook.pytest_report_teststatus(
|
||||||
report=report, config=self.config
|
report=report, config=self.config
|
||||||
)
|
)
|
||||||
code = res[1]
|
code = res[1] # type: str
|
||||||
if code == "x":
|
if code == "x":
|
||||||
longrepr = str(report.longrepr)
|
longrepr = str(report.longrepr)
|
||||||
elif code == "X":
|
elif code == "X":
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
import os
|
import os
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
from typing import List
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest.pytester import Testdir
|
||||||
from _pytest.resultlog import pytest_configure
|
from _pytest.resultlog import pytest_configure
|
||||||
from _pytest.resultlog import pytest_unconfigure
|
from _pytest.resultlog import pytest_unconfigure
|
||||||
from _pytest.resultlog import ResultLog
|
from _pytest.resultlog import ResultLog
|
||||||
from _pytest.resultlog import resultlog_key
|
from _pytest.resultlog import resultlog_key
|
||||||
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.filterwarnings("ignore:--result-log is deprecated")
|
pytestmark = pytest.mark.filterwarnings("ignore:--result-log is deprecated")
|
||||||
|
|
||||||
|
|
||||||
def test_write_log_entry():
|
def test_write_log_entry() -> None:
|
||||||
reslog = ResultLog(None, None)
|
reslog = ResultLog(None, None) # type: ignore[arg-type]
|
||||||
reslog.logfile = StringIO()
|
reslog.logfile = StringIO()
|
||||||
reslog.write_log_entry("name", ".", "")
|
reslog.write_log_entry("name", ".", "")
|
||||||
entry = reslog.logfile.getvalue()
|
entry = reslog.logfile.getvalue()
|
||||||
|
@ -54,14 +57,14 @@ class TestWithFunctionIntegration:
|
||||||
# XXX (hpk) i think that the resultlog plugin should
|
# XXX (hpk) i think that the resultlog plugin should
|
||||||
# provide a Parser object so that one can remain
|
# provide a Parser object so that one can remain
|
||||||
# ignorant regarding formatting details.
|
# ignorant regarding formatting details.
|
||||||
def getresultlog(self, testdir, arg):
|
def getresultlog(self, testdir: Testdir, arg: str) -> List[str]:
|
||||||
resultlog = testdir.tmpdir.join("resultlog")
|
resultlog = testdir.tmpdir.join("resultlog")
|
||||||
testdir.plugins.append("resultlog")
|
testdir.plugins.append("resultlog")
|
||||||
args = ["--resultlog=%s" % resultlog] + [arg]
|
args = ["--resultlog=%s" % resultlog] + [arg]
|
||||||
testdir.runpytest(*args)
|
testdir.runpytest(*args)
|
||||||
return [x for x in resultlog.readlines(cr=0) if x]
|
return [x for x in resultlog.readlines(cr=0) if x]
|
||||||
|
|
||||||
def test_collection_report(self, testdir):
|
def test_collection_report(self, testdir: Testdir) -> None:
|
||||||
ok = testdir.makepyfile(test_collection_ok="")
|
ok = testdir.makepyfile(test_collection_ok="")
|
||||||
fail = testdir.makepyfile(test_collection_fail="XXX")
|
fail = testdir.makepyfile(test_collection_fail="XXX")
|
||||||
lines = self.getresultlog(testdir, ok)
|
lines = self.getresultlog(testdir, ok)
|
||||||
|
@ -75,7 +78,7 @@ class TestWithFunctionIntegration:
|
||||||
assert x.startswith(" ")
|
assert x.startswith(" ")
|
||||||
assert "XXX" in "".join(lines[1:])
|
assert "XXX" in "".join(lines[1:])
|
||||||
|
|
||||||
def test_log_test_outcomes(self, testdir):
|
def test_log_test_outcomes(self, testdir: Testdir) -> None:
|
||||||
mod = testdir.makepyfile(
|
mod = testdir.makepyfile(
|
||||||
test_mod="""
|
test_mod="""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -111,16 +114,17 @@ class TestWithFunctionIntegration:
|
||||||
assert len(lines) == 15
|
assert len(lines) == 15
|
||||||
|
|
||||||
@pytest.mark.parametrize("style", ("native", "long", "short"))
|
@pytest.mark.parametrize("style", ("native", "long", "short"))
|
||||||
def test_internal_exception(self, style):
|
def test_internal_exception(self, style) -> None:
|
||||||
# they are produced for example by a teardown failing
|
# they are produced for example by a teardown failing
|
||||||
# at the end of the run or a failing hook invocation
|
# at the end of the run or a failing hook invocation
|
||||||
try:
|
try:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except ValueError:
|
except ValueError:
|
||||||
excinfo = _pytest._code.ExceptionInfo.from_current()
|
excinfo = _pytest._code.ExceptionInfo.from_current()
|
||||||
reslog = ResultLog(None, StringIO())
|
file = StringIO()
|
||||||
|
reslog = ResultLog(None, file) # type: ignore[arg-type]
|
||||||
reslog.pytest_internalerror(excinfo.getrepr(style=style))
|
reslog.pytest_internalerror(excinfo.getrepr(style=style))
|
||||||
entry = reslog.logfile.getvalue()
|
entry = file.getvalue()
|
||||||
entry_lines = entry.splitlines()
|
entry_lines = entry.splitlines()
|
||||||
|
|
||||||
assert entry_lines[0].startswith("! ")
|
assert entry_lines[0].startswith("! ")
|
||||||
|
@ -130,7 +134,7 @@ class TestWithFunctionIntegration:
|
||||||
assert "ValueError" in entry
|
assert "ValueError" in entry
|
||||||
|
|
||||||
|
|
||||||
def test_generic(testdir, LineMatcher):
|
def test_generic(testdir: Testdir, LineMatcher) -> None:
|
||||||
testdir.plugins.append("resultlog")
|
testdir.plugins.append("resultlog")
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -162,7 +166,7 @@ def test_generic(testdir, LineMatcher):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_makedir_for_resultlog(testdir, LineMatcher):
|
def test_makedir_for_resultlog(testdir: Testdir, LineMatcher) -> None:
|
||||||
"""--resultlog should automatically create directories for the log file"""
|
"""--resultlog should automatically create directories for the log file"""
|
||||||
testdir.plugins.append("resultlog")
|
testdir.plugins.append("resultlog")
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
|
@ -177,7 +181,7 @@ def test_makedir_for_resultlog(testdir, LineMatcher):
|
||||||
LineMatcher(lines).fnmatch_lines([". *:test_pass"])
|
LineMatcher(lines).fnmatch_lines([". *:test_pass"])
|
||||||
|
|
||||||
|
|
||||||
def test_no_resultlog_on_workers(testdir):
|
def test_no_resultlog_on_workers(testdir: Testdir) -> None:
|
||||||
config = testdir.parseconfig("-p", "resultlog", "--resultlog=resultlog")
|
config = testdir.parseconfig("-p", "resultlog", "--resultlog=resultlog")
|
||||||
|
|
||||||
assert resultlog_key not in config._store
|
assert resultlog_key not in config._store
|
||||||
|
@ -186,14 +190,14 @@ def test_no_resultlog_on_workers(testdir):
|
||||||
pytest_unconfigure(config)
|
pytest_unconfigure(config)
|
||||||
assert resultlog_key not in config._store
|
assert resultlog_key not in config._store
|
||||||
|
|
||||||
config.workerinput = {}
|
config.workerinput = {} # type: ignore[attr-defined]
|
||||||
pytest_configure(config)
|
pytest_configure(config)
|
||||||
assert resultlog_key not in config._store
|
assert resultlog_key not in config._store
|
||||||
pytest_unconfigure(config)
|
pytest_unconfigure(config)
|
||||||
assert resultlog_key not in config._store
|
assert resultlog_key not in config._store
|
||||||
|
|
||||||
|
|
||||||
def test_unknown_teststatus(testdir):
|
def test_unknown_teststatus(testdir: Testdir) -> None:
|
||||||
"""Ensure resultlog correctly handles unknown status from pytest_report_teststatus
|
"""Ensure resultlog correctly handles unknown status from pytest_report_teststatus
|
||||||
|
|
||||||
Inspired on pytest-rerunfailures.
|
Inspired on pytest-rerunfailures.
|
||||||
|
@ -229,7 +233,7 @@ def test_unknown_teststatus(testdir):
|
||||||
assert lines[0] == "r test_unknown_teststatus.py::test"
|
assert lines[0] == "r test_unknown_teststatus.py::test"
|
||||||
|
|
||||||
|
|
||||||
def test_failure_issue380(testdir):
|
def test_failure_issue380(testdir: Testdir) -> None:
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
Loading…
Reference in New Issue