pytest_terminal_summary uses result from pytest_report_teststatus hook, rather than hardcoded strings

Less hacky way to make XPASS yellow markup. Make sure collect reports still have a "when" attribute.

xfail changed to XFAIL in the test report, for consistency with other outcomes which are all CAPS
This commit is contained in:
wim glenn 2019-01-22 23:26:30 -06:00
parent ba452dbcf0
commit 0f546c4670
No known key found for this signature in database
GPG Key ID: C127F552CFFFC6DE
8 changed files with 41 additions and 33 deletions

View File

@ -0,0 +1 @@
``pytest_terminal_summary`` uses result from ``pytest_report_teststatus`` hook, rather than hardcoded strings.

View File

@ -213,7 +213,7 @@ class _NodeReporter(object):
self._add_simple(Junit.skipped, "collection skipped", report.longrepr)
def append_error(self, report):
if getattr(report, "when", None) == "teardown":
if report.when == "teardown":
msg = "test teardown failure"
else:
msg = "test setup failure"

View File

@ -19,6 +19,8 @@ def getslaveinfoline(node):
class BaseReport(object):
when = None
def __init__(self, **kw):
self.__dict__.update(kw)
@ -169,6 +171,8 @@ class TeardownErrorReport(BaseReport):
class CollectReport(BaseReport):
when = "collect"
def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra):
self.nodeid = nodeid
self.outcome = outcome

View File

@ -180,9 +180,9 @@ def pytest_runtest_makereport(item, call):
def pytest_report_teststatus(report):
if hasattr(report, "wasxfail"):
if report.skipped:
return "xfailed", "x", "xfail"
return "xfailed", "x", "XFAIL"
elif report.passed:
return "xpassed", "X", ("XPASS", {"yellow": True})
return "xpassed", "X", "XPASS"
# called by the terminalreporter instance/plugin
@ -191,11 +191,6 @@ def pytest_report_teststatus(report):
def pytest_terminal_summary(terminalreporter):
tr = terminalreporter
if not tr.reportchars:
# for name in "xfailed skipped failed xpassed":
# if not tr.stats.get(name, 0):
# tr.write_line("HINT: use '-r' option to see extra "
# "summary info about tests")
# break
return
lines = []
@ -209,21 +204,23 @@ def pytest_terminal_summary(terminalreporter):
tr._tw.line(line)
def show_simple(terminalreporter, lines, stat, format):
def show_simple(terminalreporter, lines, stat):
failed = terminalreporter.stats.get(stat)
if failed:
for rep in failed:
verbose_word = _get_report_str(terminalreporter, rep)
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
lines.append(format % (pos,))
lines.append("%s %s" % (verbose_word, pos))
def show_xfailed(terminalreporter, lines):
xfailed = terminalreporter.stats.get("xfailed")
if xfailed:
for rep in xfailed:
verbose_word = _get_report_str(terminalreporter, rep)
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
reason = rep.wasxfail
lines.append("XFAIL %s" % (pos,))
lines.append("%s %s" % (verbose_word, pos))
if reason:
lines.append(" " + str(reason))
@ -232,9 +229,10 @@ def show_xpassed(terminalreporter, lines):
xpassed = terminalreporter.stats.get("xpassed")
if xpassed:
for rep in xpassed:
verbose_word = _get_report_str(terminalreporter, rep)
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
reason = rep.wasxfail
lines.append("XPASS %s %s" % (pos, reason))
lines.append("%s %s %s" % (verbose_word, pos, reason))
def folded_skips(skipped):
@ -260,39 +258,42 @@ def show_skipped(terminalreporter, lines):
tr = terminalreporter
skipped = tr.stats.get("skipped", [])
if skipped:
# if not tr.hasopt('skipped'):
# tr.write_line(
# "%d skipped tests, specify -rs for more info" %
# len(skipped))
# return
verbose_word = _get_report_str(terminalreporter, report=skipped[0])
fskips = folded_skips(skipped)
if fskips:
# tr.write_sep("_", "skipped test summary")
for num, fspath, lineno, reason in fskips:
if reason.startswith("Skipped: "):
reason = reason[9:]
if lineno is not None:
lines.append(
"SKIP [%d] %s:%d: %s" % (num, fspath, lineno + 1, reason)
"%s [%d] %s:%d: %s"
% (verbose_word, num, fspath, lineno + 1, reason)
)
else:
lines.append("SKIP [%d] %s: %s" % (num, fspath, reason))
lines.append("%s [%d] %s: %s" % (verbose_word, num, fspath, reason))
def shower(stat, format):
def shower(stat):
def show_(terminalreporter, lines):
return show_simple(terminalreporter, lines, stat, format)
return show_simple(terminalreporter, lines, stat)
return show_
def _get_report_str(terminalreporter, report):
_category, _short, verbose = terminalreporter.config.hook.pytest_report_teststatus(
report=report
)
return verbose
REPORTCHAR_ACTIONS = {
"x": show_xfailed,
"X": show_xpassed,
"f": shower("failed", "FAIL %s"),
"F": shower("failed", "FAIL %s"),
"f": shower("failed"),
"F": shower("failed"),
"s": show_skipped,
"S": show_skipped,
"p": shower("passed", "PASSED %s"),
"E": shower("error", "ERROR %s"),
"p": shower("passed"),
"E": shower("error"),
}

View File

@ -376,8 +376,11 @@ class TerminalReporter(object):
return
running_xdist = hasattr(rep, "node")
if markup is None:
if rep.passed:
was_xfail = hasattr(report, "wasxfail")
if rep.passed and not was_xfail:
markup = {"green": True}
elif rep.passed and was_xfail:
markup = {"yellow": True}
elif rep.failed:
markup = {"red": True}
elif rep.skipped:
@ -806,8 +809,7 @@ class TerminalReporter(object):
self.write_sep("=", "ERRORS")
for rep in self.stats["error"]:
msg = self._getfailureheadline(rep)
if not hasattr(rep, "when"):
# collect
if rep.when == "collect":
msg = "ERROR collecting " + msg
elif rep.when == "setup":
msg = "ERROR at setup of " + msg

View File

@ -804,8 +804,8 @@ class TestInvocationVariants(object):
result = testdir.runpytest("-rf")
lines = result.stdout.str().splitlines()
for line in lines:
if line.startswith("FAIL "):
testid = line[5:].strip()
if line.startswith(("FAIL ", "FAILED ")):
_fail, _sep, testid = line.partition(" ")
break
result = testdir.runpytest(testid, "-rf")
result.stdout.fnmatch_lines([line, "*1 failed*"])

View File

@ -1202,6 +1202,6 @@ def test_summary_list_after_errors(testdir):
[
"=* FAILURES *=",
"*= short test summary info =*",
"FAIL test_summary_list_after_errors.py::test_fail",
"FAILED test_summary_list_after_errors.py::test_fail",
]
)

View File

@ -625,7 +625,7 @@ class TestTerminalFunctional(object):
"*test_verbose_reporting.py::test_fail *FAIL*",
"*test_verbose_reporting.py::test_pass *PASS*",
"*test_verbose_reporting.py::TestClass::test_skip *SKIP*",
"*test_verbose_reporting.py::test_gen *xfail*",
"*test_verbose_reporting.py::test_gen *XFAIL*",
]
)
assert result.ret == 1