Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/4667.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``pytest_terminal_summary`` uses result from ``pytest_report_teststatus`` hook, rather than hardcoded strings.
2 changes: 1 addition & 1 deletion src/_pytest/junitxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def append_collect_skipped(self, report):
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"
Expand Down
13 changes: 5 additions & 8 deletions src/_pytest/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,10 @@ def matchreport(
"""return a testreport whose dotted import path matches"""
values = []
for rep in self.getreports(names=names):
try:
if not when and rep.when != "call" and rep.passed:
# setup/teardown passing reports - let's ignore those
continue
except AttributeError:
pass
if when and getattr(rep, "when", None) != when:
if not when and rep.when != "call" and rep.passed:
# setup/teardown passing reports - let's ignore those
continue
if when and rep.when != when:
continue
if not inamepart or inamepart in rep.nodeid.split("::"):
values.append(rep)
Expand All @@ -338,7 +335,7 @@ def listoutcomes(self):
failed = []
for rep in self.getreports("pytest_collectreport pytest_runtest_logreport"):
if rep.passed:
if getattr(rep, "when", None) == "call":
if rep.when == "call":
passed.append(rep)
elif rep.skipped:
skipped.append(rep)
Expand Down
4 changes: 4 additions & 0 deletions src/_pytest/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ def getslaveinfoline(node):


class BaseReport(object):
when = None

def __init__(self, **kw):
self.__dict__.update(kw)

Expand Down Expand Up @@ -169,6 +171,8 @@ def __init__(self, longrepr, **extra):


class CollectReport(BaseReport):
when = "collect"

def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra):
self.nodeid = nodeid
self.outcome = outcome
Expand Down
58 changes: 31 additions & 27 deletions src/_pytest/skipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 = []
Expand All @@ -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))

Expand All @@ -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):
Expand All @@ -246,8 +244,11 @@ def folded_skips(skipped):
# folding reports with global pytestmark variable
# this is workaround, because for now we cannot identify the scope of a skip marker
# TODO: revisit after marks scope would be fixed
when = getattr(event, "when", None)
if when == "setup" and "skip" in keywords and "pytestmark" not in keywords:
if (
event.when == "setup"
and "skip" in keywords
and "pytestmark" not in keywords
):
key = (key[0], None, key[2])
d.setdefault(key, []).append(event)
values = []
Expand All @@ -260,39 +261,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"),
}
8 changes: 5 additions & 3 deletions src/_pytest/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,11 @@ def pytest_runtest_logreport(self, report):
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:
Expand Down Expand Up @@ -806,8 +809,7 @@ def summary_errors(self):
self.write_sep("=", "ERRORS")
for rep in self.stats["error"]:
msg = self._getfailureheadline(rep)
if not hasattr(rep, "when"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

# collect
if rep.when == "collect":
msg = "ERROR collecting " + msg
elif rep.when == "setup":
msg = "ERROR at setup of " + msg
Expand Down
4 changes: 2 additions & 2 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,8 @@ def test_doctest_id(self, testdir):
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*"])
Expand Down
3 changes: 2 additions & 1 deletion testing/test_skipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ class X(object):

# ev3 might be a collection report
ev3 = X()
ev3.when = "collect"
ev3.longrepr = longrepr
ev3.skipped = True

Expand Down Expand Up @@ -1202,6 +1203,6 @@ def test_fail():
[
"=* FAILURES *=",
"*= short test summary info =*",
"FAIL test_summary_list_after_errors.py::test_fail",
"FAILED test_summary_list_after_errors.py::test_fail",
]
)
2 changes: 1 addition & 1 deletion testing/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ def test_verbose_reporting(self, verbose_testfile, testdir, pytestconfig):
"*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
Expand Down