Merge branch 'esiegerman/summary_colors' of github.com:esiegerman/pytest

This commit is contained in:
Bruno Oliveira 2015-07-03 18:29:17 -03:00
commit d10054a38d
4 changed files with 98 additions and 19 deletions

View File

@ -25,6 +25,7 @@ Daniel Nuri
Dave Hunt Dave Hunt
David Mohr David Mohr
Eduardo Schettino Eduardo Schettino
Eric Siegerman
Florian Bruhin Florian Bruhin
Edison Gustavo Muenz Edison Gustavo Muenz
Floris Bruynooghe Floris Bruynooghe

View File

@ -1,6 +1,9 @@
2.8.0.dev (compared to 2.7.X) 2.8.0.dev (compared to 2.7.X)
----------------------------- -----------------------------
- partial fix for issue500: color the summary bar yellow for warning
situations, including the case where no tests were run
- fix issue713: JUnit XML reports for doctest failures. - fix issue713: JUnit XML reports for doctest failures.
Thanks Punyashloka Biswal. Thanks Punyashloka Biswal.

View File

@ -487,26 +487,9 @@ class TerminalReporter:
def summary_stats(self): def summary_stats(self):
session_duration = time.time() - self._sessionstarttime session_duration = time.time() - self._sessionstarttime
(line, color) = build_summary_stats_line(self.stats)
keys = ("failed passed skipped deselected "
"xfailed xpassed warnings").split()
for key in self.stats.keys():
if key not in keys:
keys.append(key)
parts = []
for key in keys:
if key: # setup/teardown reports have an empty key, ignore them
val = self.stats.get(key, None)
if val:
parts.append("%d %s" % (len(val), key))
line = ", ".join(parts)
msg = "%s in %.2f seconds" % (line, session_duration) msg = "%s in %.2f seconds" % (line, session_duration)
markup = {color: True, 'bold': True}
markup = {'bold': True}
if 'failed' in self.stats or 'error' in self.stats:
markup = {'red': True, 'bold': True}
else:
markup = {'green': True, 'bold': True}
if self.verbosity >= 0: if self.verbosity >= 0:
self.write_sep("=", msg, **markup) self.write_sep("=", msg, **markup)
@ -542,3 +525,29 @@ def flatten(l):
else: else:
yield x yield x
def build_summary_stats_line(stats):
keys = ("failed passed skipped deselected "
"xfailed xpassed warnings error").split()
unknown_key_seen = False
for key in stats.keys():
if key not in keys:
if key: # setup/teardown reports have an empty key, ignore them
keys.append(key)
unknown_key_seen = True
parts = []
for key in keys:
val = stats.get(key, None)
if val:
parts.append("%d %s" % (len(val), key))
line = ", ".join(parts)
if 'failed' in stats or 'error' in stats:
color = 'red'
elif 'warnings' in stats or unknown_key_seen:
color = 'yellow'
elif 'passed' in stats:
color = 'green'
else:
color = 'yellow'
return (line, color)

View File

@ -7,6 +7,7 @@ import pluggy
import sys import sys
from _pytest.terminal import TerminalReporter, repr_pythonversion, getreportopt from _pytest.terminal import TerminalReporter, repr_pythonversion, getreportopt
from _pytest.terminal import build_summary_stats_line
from _pytest import runner from _pytest import runner
def basic_run_report(item): def basic_run_report(item):
@ -718,3 +719,68 @@ def test_terminal_summary(testdir):
*==== hello ====* *==== hello ====*
world world
""") """)
@pytest.mark.parametrize("exp_color, exp_line, stats_arg", [
# The method under test only cares about the length of each
# dict value, not the actual contents, so tuples of anything
# suffice
# Important statuses -- the highest priority of these always wins
("red", "1 failed", {"failed": (1,)}),
("red", "1 failed, 1 passed", {"failed": (1,), "passed": (1,)}),
("red", "1 error", {"error": (1,)}),
("red", "1 passed, 1 error", {"error": (1,), "passed": (1,)}),
# (a status that's not known to the code)
("yellow", "1 weird", {"weird": (1,)}),
("yellow", "1 passed, 1 weird", {"weird": (1,), "passed": (1,)}),
("yellow", "1 warnings", {"warnings": (1,)}),
("yellow", "1 passed, 1 warnings", {"warnings": (1,), "passed": (1,)}),
("green", "5 passed", {"passed": (1,2,3,4,5)}),
# "Boring" statuses. These have no effect on the color of the summary
# line. Thus, if *every* test has a boring status, the summary line stays
# at its default color, i.e. yellow, to warn the user that the test run
# produced no useful information
("yellow", "1 skipped", {"skipped": (1,)}),
("green", "1 passed, 1 skipped", {"skipped": (1,), "passed": (1,)}),
("yellow", "1 deselected", {"deselected": (1,)}),
("green", "1 passed, 1 deselected", {"deselected": (1,), "passed": (1,)}),
("yellow", "1 xfailed", {"xfailed": (1,)}),
("green", "1 passed, 1 xfailed", {"xfailed": (1,), "passed": (1,)}),
("yellow", "1 xpassed", {"xpassed": (1,)}),
("green", "1 passed, 1 xpassed", {"xpassed": (1,), "passed": (1,)}),
# Likewise if no tests were found at all
("yellow", "", {}),
# Test the empty-key special case
("yellow", "", {"": (1,)}),
("green", "1 passed", {"": (1,), "passed": (1,)}),
# A couple more complex combinations
("red", "1 failed, 2 passed, 3 xfailed",
{"passed": (1,2), "failed": (1,), "xfailed": (1,2,3)}),
("green", "1 passed, 2 skipped, 3 deselected, 2 xfailed",
{"passed": (1,),
"skipped": (1,2),
"deselected": (1,2,3),
"xfailed": (1,2)}),
])
def test_summary_stats(exp_line, exp_color, stats_arg):
print("Based on stats: %s" % stats_arg)
print("Expect summary: \"%s\"; with color \"%s\"" % (exp_line, exp_color))
(line, color) = build_summary_stats_line(stats_arg)
print("Actually got: \"%s\"; with color \"%s\"" % (line, color))
assert line == exp_line
assert color == exp_color