Skip to content

Commit 051bdf2

Browse files
lordjabeznedbat
authored andcommitted
Always output TOTAL line.
1 parent 7ff93a9 commit 051bdf2

8 files changed

+76
-37
lines changed

CHANGES.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ want to know what's different in 5.0 since 4.5.x, see :ref:`whatsnew5x`.
2424
Unreleased
2525
----------
2626

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

3031
.. _changes_531:
3132

CONTRIBUTORS.txt

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Jon Chappell
7979
Jon Dufresne
8080
Joseph Tate
8181
Josh Williams
82+
Judson Neer
8283
Julian Berman
8384
Julien Voisin
8485
Justas Sadzevičius

coverage/summary.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ def report(self, morfs, outfile=None):
120120
for line in lines:
121121
self.writeout(line[0])
122122

123-
# Write a TOTAl line if we had more than one file.
124-
if self.total.n_files > 1:
123+
# Write a TOTAL line if we had at least one file.
124+
if self.total.n_files > 0:
125125
self.writeout(rule)
126126
args = ("TOTAL", self.total.n_statements, self.total.n_missing)
127127
if self.branches:

tests/test_api.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,11 @@ def test_completely_zero_reporting(self):
306306
# Name Stmts Miss Cover
307307
# --------------------------------
308308
# foo/bar.py 1 1 0%
309+
# --------------------------------
310+
# TOTAL 1 1 0%
309311

310-
last = self.last_line_squeezed(self.stdout()).replace("\\", "/")
311-
self.assertEqual("foo/bar.py 1 1 0%", last)
312+
last = self.last_line_squeezed(self.stdout())
313+
self.assertEqual("TOTAL 1 1 0%", last)
312314

313315
def test_cov4_data_file(self):
314316
cov4_data = (
@@ -587,6 +589,8 @@ def test_source_and_include_dont_conflict(self):
587589
Name Stmts Miss Cover
588590
---------------------------
589591
b.py 1 0 100%
592+
---------------------------
593+
TOTAL 1 0 100%
590594
""")
591595
self.assertEqual(expected, self.stdout())
592596

@@ -1049,6 +1053,8 @@ def pretend_to_be_nose_with_cover(self, erase=False, cd=False):
10491053
Name Stmts Miss Cover Missing
10501054
--------------------------------------------
10511055
no_biggie.py 4 1 75% 4
1056+
--------------------------------------------
1057+
TOTAL 4 1 75%
10521058
"""))
10531059
if cd:
10541060
os.chdir("..")
@@ -1092,6 +1098,8 @@ def pretend_to_be_pytestcov(self, append):
10921098
Name Stmts Miss Cover
10931099
-----------------------------
10941100
prog.py 4 1 75%
1101+
-----------------------------
1102+
TOTAL 4 1 75%
10951103
"""))
10961104
self.assert_file_count(".coverage", 0)
10971105
self.assert_file_count(".coverage.*", 1)

tests/test_concurrency.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ def try_multiprocessing_code(
409409
out = self.run_command("coverage report -m")
410410

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

414414
def test_multiprocessing_simple(self):
415415
nprocs = 3
@@ -466,7 +466,7 @@ def try_multiprocessing_code_with_branching(self, code, expected_out):
466466
out = self.run_command("coverage report -m")
467467

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

471471
def test_multiprocessing_with_branching(self):
472472
nprocs = 3

tests/test_plugins.py

+2
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ def coverage_init(reg, options):
522522
'Name Stmts Miss Cover Missing',
523523
'-----------------------------------------------',
524524
'unsuspecting.py 6 3 50% 2, 4, 6',
525+
'-----------------------------------------------',
526+
'TOTAL 6 3 50%',
525527
]
526528
self.assertEqual(expected, report)
527529
self.assertEqual(total, 50)

tests/test_process.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ def test_combine_with_rc(self):
341341
Name Stmts Miss Cover
342342
-------------------------------
343343
b_or_c.py 8 0 100%
344+
-------------------------------
345+
TOTAL 8 0 100%
344346
"""))
345347

346348
def test_combine_with_aliases(self):
@@ -1231,7 +1233,7 @@ def setUp(self):
12311233
def test_report_43_is_ok(self):
12321234
st, out = self.run_command_status("coverage report --fail-under=43")
12331235
self.assertEqual(st, 0)
1234-
self.assertEqual(self.last_line_squeezed(out), "forty_two_plus.py 7 4 43%")
1236+
self.assertEqual(self.last_line_squeezed(out), "TOTAL 7 4 43%")
12351237

12361238
def test_report_43_is_not_ok(self):
12371239
st, out = self.run_command_status("coverage report --fail-under=44")
@@ -1305,6 +1307,8 @@ def test_accented_dot_py(self):
13051307
u"Name Stmts Miss Cover\n"
13061308
u"----------------------------\n"
13071309
u"h\xe2t.py 1 0 100%\n"
1310+
u"----------------------------\n"
1311+
u"TOTAL 1 0 100%\n"
13081312
)
13091313

13101314
if env.PY2:
@@ -1348,8 +1352,10 @@ def test_accented_directory(self):
13481352
report_expected = (
13491353
u"Name Stmts Miss Cover\n"
13501354
u"-----------------------------------\n"
1351-
u"\xe2%saccented.py 1 0 100%%\n" % os.sep
1352-
)
1355+
u"\xe2%saccented.py 1 0 100%%\n"
1356+
u"-----------------------------------\n"
1357+
u"TOTAL 1 0 100%%\n"
1358+
) % os.sep
13531359

13541360
if env.PY2:
13551361
report_expected = report_expected.encode(output_encoding())

tests/test_summary.py

+47-26
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ def test_report_just_one(self):
7070
# Name Stmts Miss Cover
7171
# -------------------------------
7272
# mycode.py 4 0 100%
73+
# -------------------------------
74+
# TOTAL 4 0 100%
7375

74-
self.assertEqual(self.line_count(report), 3)
76+
self.assertEqual(self.line_count(report), 5)
7577
self.assertNotIn("/coverage/", report)
7678
self.assertNotIn("/tests/modules/covmod1.py ", report)
7779
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
7880
self.assertIn("mycode.py ", report)
79-
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
81+
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")
8082

8183
def test_report_wildcard(self):
8284
# Try reporting using wildcards to get the modules.
@@ -87,13 +89,15 @@ def test_report_wildcard(self):
8789
# Name Stmts Miss Cover
8890
# -------------------------------
8991
# mycode.py 4 0 100%
92+
# -------------------------------
93+
# TOTAL 4 0 100%
9094

91-
self.assertEqual(self.line_count(report), 3)
95+
self.assertEqual(self.line_count(report), 5)
9296
self.assertNotIn("/coverage/", report)
9397
self.assertNotIn("/tests/modules/covmod1.py ", report)
9498
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
9599
self.assertIn("mycode.py ", report)
96-
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
100+
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")
97101

98102
def test_report_omitting(self):
99103
# Try reporting while omitting some modules
@@ -105,13 +109,15 @@ def test_report_omitting(self):
105109
# Name Stmts Miss Cover
106110
# -------------------------------
107111
# mycode.py 4 0 100%
112+
# -------------------------------
113+
# TOTAL 4 0 100%
108114

109-
self.assertEqual(self.line_count(report), 3)
115+
self.assertEqual(self.line_count(report), 5)
110116
self.assertNotIn("/coverage/", report)
111117
self.assertNotIn("/tests/modules/covmod1.py ", report)
112118
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
113119
self.assertIn("mycode.py ", report)
114-
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
120+
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")
115121

116122
def test_report_including(self):
117123
# Try reporting while including some modules
@@ -122,13 +128,15 @@ def test_report_including(self):
122128
# Name Stmts Miss Cover
123129
# -------------------------------
124130
# mycode.py 4 0 100%
131+
# -------------------------------
132+
# TOTAL 4 0 100%
125133

126-
self.assertEqual(self.line_count(report), 3)
134+
self.assertEqual(self.line_count(report), 5)
127135
self.assertNotIn("/coverage/", report)
128136
self.assertNotIn("/tests/modules/covmod1.py ", report)
129137
self.assertNotIn("/tests/zipmods.zip/covmodzip1.py ", report)
130138
self.assertIn("mycode.py ", report)
131-
self.assertEqual(self.last_line_squeezed(report), "mycode.py 4 0 100%")
139+
self.assertEqual(self.last_line_squeezed(report), "TOTAL 4 0 100%")
132140

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

180188
# Name Stmts Miss Branch BrPart Cover
181189
# -----------------------------------------------
182-
# mybranch.py 5 0 2 1 85%
190+
# mybranch.py 5 0 2 1 86%
191+
# -----------------------------------------------
192+
# TOTAL 5 0 2 1 86%
183193

184-
self.assertEqual(self.line_count(report), 3)
194+
self.assertEqual(self.line_count(report), 5)
185195
self.assertIn("mybranch.py ", report)
186-
self.assertEqual(self.last_line_squeezed(report), "mybranch.py 5 0 2 1 86%")
196+
self.assertEqual(self.last_line_squeezed(report), "TOTAL 5 0 2 1 86%")
187197

188198
def test_report_show_missing(self):
189199
self.make_file("mymissing.py", """\
@@ -209,10 +219,13 @@ def missing(x, y):
209219
# Name Stmts Miss Cover Missing
210220
# --------------------------------------------
211221
# mymissing.py 14 3 79% 3-4, 10
222+
# --------------------------------------------
223+
# TOTAL 14 3 79% 3-4, 10
212224

213-
self.assertEqual(self.line_count(report), 3)
214-
self.assertIn("mymissing.py ", report)
215-
self.assertEqual(self.last_line_squeezed(report), "mymissing.py 14 3 79% 3-4, 10")
225+
self.assertEqual(self.line_count(report), 5)
226+
squeezed = self.squeezed_lines(report)
227+
self.assertEqual(squeezed[2], "mymissing.py 14 3 79% 3-4, 10")
228+
self.assertEqual(squeezed[4], "TOTAL 14 3 79%")
216229

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

235-
self.assertEqual(self.line_count(report), 3)
236-
self.assertIn("mybranch.py ", report)
237-
self.assertEqual(self.last_line_squeezed(report), "mybranch.py 6 0 4 2 80% 2->4, 4->exit")
250+
self.assertEqual(self.line_count(report), 5)
251+
squeezed = self.squeezed_lines(report)
252+
self.assertEqual(squeezed[2], "mybranch.py 6 0 4 2 80% 2->4, 4->exit")
253+
self.assertEqual(squeezed[4], "TOTAL 6 0 4 2 80%")
238254

239255
def test_report_show_missing_branches_and_lines(self):
240256
self.make_file("main.py", """\
@@ -394,12 +410,14 @@ def foo():
394410

395411
# Name Stmts Miss Branch BrPart Cover
396412
# -------------------------------------------
413+
# -----------------------------------------
414+
# TOTAL 3 0 0 0 100%
397415
#
398416
# 1 file skipped due to complete coverage.
399417

400-
self.assertEqual(self.line_count(report), 4, report)
418+
self.assertEqual(self.line_count(report), 6, report)
401419
squeezed = self.squeezed_lines(report)
402-
self.assertEqual(squeezed[3], "1 file skipped due to complete coverage.")
420+
self.assertEqual(squeezed[5], "1 file skipped due to complete coverage.")
403421

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

414432
# Name Stmts Miss Branch BrPart Cover
415433
# -----------------------------------------
434+
# -----------------------------------------
435+
# TOTAL 3 0 0 0 100%
416436
#
417437
# 1 file skipped due to complete coverage.
418438

419-
self.assertEqual(self.line_count(report), 4, report)
439+
self.assertEqual(self.line_count(report), 6, report)
420440
lines = self.report_lines(report)
421441
self.assertEqual(lines[0], "Name Stmts Miss Branch BrPart Cover")
422442
squeezed = self.squeezed_lines(report)
423-
self.assertEqual(squeezed[3], "1 file skipped due to complete coverage.")
443+
self.assertEqual(squeezed[5], "1 file skipped due to complete coverage.")
424444

425445
def test_report_skip_covered_no_data(self):
426446
report = self.report_from_command("coverage report --skip-covered")
@@ -472,9 +492,10 @@ def test_report_skip_empty_no_data(self):
472492
#
473493
# 1 empty file skipped.
474494

475-
self.assertEqual(self.line_count(report), 4, report)
476-
lines = self.report_lines(report)
477-
self.assertEqual(lines[3], "1 empty file skipped.")
495+
self.assertEqual(self.line_count(report), 6, report)
496+
squeezed = self.squeezed_lines(report)
497+
self.assertEqual(squeezed[3], "TOTAL 0 0 100%")
498+
self.assertEqual(squeezed[5], "1 empty file skipped.")
478499

479500
def test_report_precision(self):
480501
self.make_file(".coveragerc", """\
@@ -621,7 +642,7 @@ def test_report_no_extension(self):
621642
out = self.run_command("coverage run --source=. xxx")
622643
self.assertEqual(out, "xxx: 3 4 0 7\n")
623644
report = self.report_from_command("coverage report")
624-
self.assertEqual(self.last_line_squeezed(report), "xxx 7 1 86%")
645+
self.assertEqual(self.last_line_squeezed(report), "TOTAL 7 1 86%")
625646

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

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

0 commit comments

Comments
 (0)