Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always output TOTAL line. #1091

Merged
merged 1 commit into from
Jan 6, 2021
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
5 changes: 3 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ want to know what's different in 5.0 since 4.5.x, see :ref:`whatsnew5x`.
Unreleased
----------

Nothing yet.

- The text report produced by ``coverage report`` now always outputs a TOTAL
line, even if only one Python file is reported. This makes regex parsing
of the output easier. Thanks, Judson Neer.

.. _changes_531:

Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Jon Chappell
Jon Dufresne
Joseph Tate
Josh Williams
Judson Neer
Julian Berman
Julien Voisin
Justas Sadzevičius
Expand Down
4 changes: 2 additions & 2 deletions coverage/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ def report(self, morfs, outfile=None):
for line in lines:
self.writeout(line[0])

# Write a TOTAl line if we had more than one file.
if self.total.n_files > 1:
# Write a TOTAL line if we had at least one file.
if self.total.n_files > 0:
self.writeout(rule)
args = ("TOTAL", self.total.n_statements, self.total.n_missing)
if self.branches:
Expand Down
12 changes: 10 additions & 2 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,11 @@ def test_completely_zero_reporting(self):
# Name Stmts Miss Cover
# --------------------------------
# foo/bar.py 1 1 0%
# --------------------------------
# TOTAL 1 1 0%

last = self.last_line_squeezed(self.stdout()).replace("\\", "/")
self.assertEqual("foo/bar.py 1 1 0%", last)
last = self.last_line_squeezed(self.stdout())
self.assertEqual("TOTAL 1 1 0%", last)

def test_cov4_data_file(self):
cov4_data = (
Expand Down Expand Up @@ -587,6 +589,8 @@ def test_source_and_include_dont_conflict(self):
Name Stmts Miss Cover
---------------------------
b.py 1 0 100%
---------------------------
TOTAL 1 0 100%
""")
self.assertEqual(expected, self.stdout())

Expand Down Expand Up @@ -1049,6 +1053,8 @@ def pretend_to_be_nose_with_cover(self, erase=False, cd=False):
Name Stmts Miss Cover Missing
--------------------------------------------
no_biggie.py 4 1 75% 4
--------------------------------------------
TOTAL 4 1 75%
"""))
if cd:
os.chdir("..")
Expand Down Expand Up @@ -1092,6 +1098,8 @@ def pretend_to_be_pytestcov(self, append):
Name Stmts Miss Cover
-----------------------------
prog.py 4 1 75%
-----------------------------
TOTAL 4 1 75%
"""))
self.assert_file_count(".coverage", 0)
self.assert_file_count(".coverage.*", 1)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_concurrency.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ def try_multiprocessing_code(
out = self.run_command("coverage report -m")

last_line = self.squeezed_lines(out)[-1]
self.assertRegex(last_line, r"multi.py \d+ 0 100%")
self.assertRegex(last_line, r"TOTAL \d+ 0 100%")

def test_multiprocessing_simple(self):
nprocs = 3
Expand Down Expand Up @@ -466,7 +466,7 @@ def try_multiprocessing_code_with_branching(self, code, expected_out):
out = self.run_command("coverage report -m")

last_line = self.squeezed_lines(out)[-1]
self.assertRegex(last_line, r"multi.py \d+ 0 \d+ 0 100%")
self.assertRegex(last_line, r"TOTAL \d+ 0 \d+ 0 100%")

def test_multiprocessing_with_branching(self):
nprocs = 3
Expand Down
2 changes: 2 additions & 0 deletions tests/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ def coverage_init(reg, options):
'Name Stmts Miss Cover Missing',
'-----------------------------------------------',
'unsuspecting.py 6 3 50% 2, 4, 6',
'-----------------------------------------------',
'TOTAL 6 3 50%',
]
self.assertEqual(expected, report)
self.assertEqual(total, 50)
Expand Down
12 changes: 9 additions & 3 deletions tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ def test_combine_with_rc(self):
Name Stmts Miss Cover
-------------------------------
b_or_c.py 8 0 100%
-------------------------------
TOTAL 8 0 100%
"""))

def test_combine_with_aliases(self):
Expand Down Expand Up @@ -1231,7 +1233,7 @@ def setUp(self):
def test_report_43_is_ok(self):
st, out = self.run_command_status("coverage report --fail-under=43")
self.assertEqual(st, 0)
self.assertEqual(self.last_line_squeezed(out), "forty_two_plus.py 7 4 43%")
self.assertEqual(self.last_line_squeezed(out), "TOTAL 7 4 43%")

def test_report_43_is_not_ok(self):
st, out = self.run_command_status("coverage report --fail-under=44")
Expand Down Expand Up @@ -1305,6 +1307,8 @@ def test_accented_dot_py(self):
u"Name Stmts Miss Cover\n"
u"----------------------------\n"
u"h\xe2t.py 1 0 100%\n"
u"----------------------------\n"
u"TOTAL 1 0 100%\n"
)

if env.PY2:
Expand Down Expand Up @@ -1348,8 +1352,10 @@ def test_accented_directory(self):
report_expected = (
u"Name Stmts Miss Cover\n"
u"-----------------------------------\n"
u"\xe2%saccented.py 1 0 100%%\n" % os.sep
)
u"\xe2%saccented.py 1 0 100%%\n"
u"-----------------------------------\n"
u"TOTAL 1 0 100%%\n"
) % os.sep

if env.PY2:
report_expected = report_expected.encode(output_encoding())
Expand Down
73 changes: 47 additions & 26 deletions tests/test_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,15 @@ def test_report_just_one(self):
# Name Stmts Miss Cover
# -------------------------------
# mycode.py 4 0 100%
# -------------------------------
# TOTAL 4 0 100%

self.assertEqual(self.line_count(report), 3)
self.assertEqual(self.line_count(report), 5)
self.assertNotIn("/coverage/", report)
self.assertNotIn("/tests/modules/covmod1.py ", report)
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
self.assertIn("mycode.py ", report)
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")

def test_report_wildcard(self):
# Try reporting using wildcards to get the modules.
Expand All @@ -87,13 +89,15 @@ def test_report_wildcard(self):
# Name Stmts Miss Cover
# -------------------------------
# mycode.py 4 0 100%
# -------------------------------
# TOTAL 4 0 100%

self.assertEqual(self.line_count(report), 3)
self.assertEqual(self.line_count(report), 5)
self.assertNotIn("/coverage/", report)
self.assertNotIn("/tests/modules/covmod1.py ", report)
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
self.assertIn("mycode.py ", report)
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")

def test_report_omitting(self):
# Try reporting while omitting some modules
Expand All @@ -105,13 +109,15 @@ def test_report_omitting(self):
# Name Stmts Miss Cover
# -------------------------------
# mycode.py 4 0 100%
# -------------------------------
# TOTAL 4 0 100%

self.assertEqual(self.line_count(report), 3)
self.assertEqual(self.line_count(report), 5)
self.assertNotIn("/coverage/", report)
self.assertNotIn("/tests/modules/covmod1.py ", report)
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
self.assertIn("mycode.py ", report)
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")

def test_report_including(self):
# Try reporting while including some modules
Expand All @@ -122,13 +128,15 @@ def test_report_including(self):
# Name Stmts Miss Cover
# -------------------------------
# mycode.py 4 0 100%
# -------------------------------
# TOTAL 4 0 100%

self.assertEqual(self.line_count(report), 3)
self.assertEqual(self.line_count(report), 5)
self.assertNotIn("/coverage/", report)
self.assertNotIn("/tests/modules/covmod1.py ", report)
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
self.assertIn("mycode.py ", report)
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")

def test_run_source_vs_report_include(self):
# https://github.com/nedbat/coveragepy/issues/621
Expand Down Expand Up @@ -179,11 +187,13 @@ def branch(x):

# Name Stmts Miss Branch BrPart Cover
# -----------------------------------------------
# mybranch.py 5 0 2 1 85%
# mybranch.py 5 0 2 1 86%
# -----------------------------------------------
# TOTAL 5 0 2 1 86%

self.assertEqual(self.line_count(report), 3)
self.assertEqual(self.line_count(report), 5)
self.assertIn("mybranch.py ", report)
self.assertEqual(self.last_line_squeezed(report), "mybranch.py 5 0 2 1 86%")
self.assertEqual(self.last_line_squeezed(report), "TOTAL 5 0 2 1 86%")

def test_report_show_missing(self):
self.make_file("mymissing.py", """\
Expand All @@ -209,10 +219,13 @@ def missing(x, y):
# Name Stmts Miss Cover Missing
# --------------------------------------------
# mymissing.py 14 3 79% 3-4, 10
# --------------------------------------------
# TOTAL 14 3 79% 3-4, 10

self.assertEqual(self.line_count(report), 3)
self.assertIn("mymissing.py ", report)
self.assertEqual(self.last_line_squeezed(report), "mymissing.py 14 3 79% 3-4, 10")
self.assertEqual(self.line_count(report), 5)
squeezed = self.squeezed_lines(report)
self.assertEqual(squeezed[2], "mymissing.py 14 3 79% 3-4, 10")
self.assertEqual(squeezed[4], "TOTAL 14 3 79%")

def test_report_show_missing_branches(self):
self.make_file("mybranch.py", """\
Expand All @@ -231,10 +244,13 @@ def branch(x, y):
# Name Stmts Miss Branch BrPart Cover Missing
# ----------------------------------------------------------
# mybranch.py 6 0 4 2 80% 2->4, 4->exit
# ----------------------------------------------------------
# TOTAL 6 0 4 2 80%

self.assertEqual(self.line_count(report), 3)
self.assertIn("mybranch.py ", report)
self.assertEqual(self.last_line_squeezed(report), "mybranch.py 6 0 4 2 80% 2->4, 4->exit")
self.assertEqual(self.line_count(report), 5)
squeezed = self.squeezed_lines(report)
self.assertEqual(squeezed[2], "mybranch.py 6 0 4 2 80% 2->4, 4->exit")
self.assertEqual(squeezed[4], "TOTAL 6 0 4 2 80%")

def test_report_show_missing_branches_and_lines(self):
self.make_file("main.py", """\
Expand Down Expand Up @@ -394,12 +410,14 @@ def foo():

# Name Stmts Miss Branch BrPart Cover
# -------------------------------------------
# -----------------------------------------
# TOTAL 3 0 0 0 100%
#
# 1 file skipped due to complete coverage.

self.assertEqual(self.line_count(report), 4, report)
self.assertEqual(self.line_count(report), 6, report)
squeezed = self.squeezed_lines(report)
self.assertEqual(squeezed[3], "1 file skipped due to complete coverage.")
self.assertEqual(squeezed[5], "1 file skipped due to complete coverage.")

def test_report_skip_covered_longfilename(self):
self.make_file("long_______________filename.py", """
Expand All @@ -413,14 +431,16 @@ def foo():

# Name Stmts Miss Branch BrPart Cover
# -----------------------------------------
# -----------------------------------------
# TOTAL 3 0 0 0 100%
#
# 1 file skipped due to complete coverage.

self.assertEqual(self.line_count(report), 4, report)
self.assertEqual(self.line_count(report), 6, report)
lines = self.report_lines(report)
self.assertEqual(lines[0], "Name Stmts Miss Branch BrPart Cover")
squeezed = self.squeezed_lines(report)
self.assertEqual(squeezed[3], "1 file skipped due to complete coverage.")
self.assertEqual(squeezed[5], "1 file skipped due to complete coverage.")

def test_report_skip_covered_no_data(self):
report = self.report_from_command("coverage report --skip-covered")
Expand Down Expand Up @@ -472,9 +492,10 @@ def test_report_skip_empty_no_data(self):
#
# 1 empty file skipped.

self.assertEqual(self.line_count(report), 4, report)
lines = self.report_lines(report)
self.assertEqual(lines[3], "1 empty file skipped.")
self.assertEqual(self.line_count(report), 6, report)
squeezed = self.squeezed_lines(report)
self.assertEqual(squeezed[3], "TOTAL 0 0 100%")
self.assertEqual(squeezed[5], "1 empty file skipped.")

def test_report_precision(self):
self.make_file(".coveragerc", """\
Expand Down Expand Up @@ -621,7 +642,7 @@ def test_report_no_extension(self):
out = self.run_command("coverage run --source=. xxx")
self.assertEqual(out, "xxx: 3 4 0 7\n")
report = self.report_from_command("coverage report")
self.assertEqual(self.last_line_squeezed(report), "xxx 7 1 86%")
self.assertEqual(self.last_line_squeezed(report), "TOTAL 7 1 86%")

def test_report_with_chdir(self):
self.make_file("chdir.py", """\
Expand All @@ -635,7 +656,7 @@ def test_report_with_chdir(self):
out = self.run_command("coverage run --source=. chdir.py")
self.assertEqual(out, "Line One\nLine Two\nhello\n")
report = self.report_from_command("coverage report")
self.assertEqual(self.last_line_squeezed(report), "chdir.py 5 0 100%")
self.assertEqual(self.last_line_squeezed(report), "TOTAL 5 0 100%")

def get_report(self, cov):
"""Get the report from `cov`, and canonicalize it."""
Expand Down