Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/_pytest/resultlog.py : 3%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1""" log machine-parseable test session result information in a plain
2text file.
3"""
4import os
6import py
8from _pytest._code.code import ExceptionRepr
9from _pytest.config import Config
10from _pytest.config.argparsing import Parser
11from _pytest.reports import CollectReport
12from _pytest.reports import TestReport
13from _pytest.store import StoreKey
16resultlog_key = StoreKey["ResultLog"]()
19def pytest_addoption(parser: Parser) -> None:
20 group = parser.getgroup("terminal reporting", "resultlog plugin options")
21 group.addoption(
22 "--resultlog",
23 "--result-log",
24 action="store",
25 metavar="path",
26 default=None,
27 help="DEPRECATED path for machine-readable result log.",
28 )
31def pytest_configure(config: Config) -> None:
32 resultlog = config.option.resultlog
33 # prevent opening resultlog on worker nodes (xdist)
34 if resultlog and not hasattr(config, "workerinput"):
35 dirname = os.path.dirname(os.path.abspath(resultlog))
36 if not os.path.isdir(dirname):
37 os.makedirs(dirname)
38 logfile = open(resultlog, "w", 1) # line buffered
39 config._store[resultlog_key] = ResultLog(config, logfile)
40 config.pluginmanager.register(config._store[resultlog_key])
42 from _pytest.deprecated import RESULT_LOG
43 from _pytest.warnings import _issue_warning_captured
45 _issue_warning_captured(RESULT_LOG, config.hook, stacklevel=2)
48def pytest_unconfigure(config: Config) -> None:
49 resultlog = config._store.get(resultlog_key, None)
50 if resultlog:
51 resultlog.logfile.close()
52 del config._store[resultlog_key]
53 config.pluginmanager.unregister(resultlog)
56class ResultLog:
57 def __init__(self, config, logfile):
58 self.config = config
59 self.logfile = logfile # preferably line buffered
61 def write_log_entry(self, testpath, lettercode, longrepr):
62 print("{} {}".format(lettercode, testpath), file=self.logfile)
63 for line in longrepr.splitlines():
64 print(" %s" % line, file=self.logfile)
66 def log_outcome(self, report, lettercode, longrepr):
67 testpath = getattr(report, "nodeid", None)
68 if testpath is None:
69 testpath = report.fspath
70 self.write_log_entry(testpath, lettercode, longrepr)
72 def pytest_runtest_logreport(self, report: TestReport) -> None:
73 if report.when != "call" and report.passed:
74 return
75 res = self.config.hook.pytest_report_teststatus(
76 report=report, config=self.config
77 )
78 code = res[1]
79 if code == "x":
80 longrepr = str(report.longrepr)
81 elif code == "X":
82 longrepr = ""
83 elif report.passed:
84 longrepr = ""
85 elif report.skipped:
86 assert report.longrepr is not None
87 longrepr = str(report.longrepr[2])
88 else:
89 longrepr = str(report.longrepr)
90 self.log_outcome(report, code, longrepr)
92 def pytest_collectreport(self, report: CollectReport) -> None:
93 if not report.passed:
94 if report.failed:
95 code = "F"
96 longrepr = str(report.longrepr)
97 else:
98 assert report.skipped
99 code = "S"
100 longrepr = "%s:%d: %s" % report.longrepr # type: ignore
101 self.log_outcome(report, code, longrepr)
103 def pytest_internalerror(self, excrepr: ExceptionRepr) -> None:
104 if excrepr.reprcrash is not None:
105 path = excrepr.reprcrash.path
106 else:
107 path = "cwd:%s" % py.path.local()
108 self.write_log_entry(path, "!", str(excrepr))