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) self._add_simple(Junit.skipped, "collection skipped", report.longrepr)
def append_error(self, report): def append_error(self, report):
if getattr(report, "when", None) == "teardown": if report.when == "teardown":
msg = "test teardown failure" msg = "test teardown failure"
else: else:
msg = "test setup failure" msg = "test setup failure"

View File

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

View File

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

View File

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

View File

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

View File

@ -1202,6 +1202,6 @@ def test_summary_list_after_errors(testdir):
[ [
"=* FAILURES *=", "=* FAILURES *=",
"*= short test summary info =*", "*= 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_fail *FAIL*",
"*test_verbose_reporting.py::test_pass *PASS*", "*test_verbose_reporting.py::test_pass *PASS*",
"*test_verbose_reporting.py::TestClass::test_skip *SKIP*", "*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 assert result.ret == 1