Skip to content

Commit 81089de

Browse files
committed
fix: module docstrings are never counted as statements
1 parent 96bd930 commit 81089de

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

CHANGES.rst

+7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ Unreleased
2626
- Fix: nested matches of exclude patterns could exclude too much code, as
2727
reported in `issue 1779`_. This is now fixed.
2828

29+
- Changed: previously, coverage.py would consider a module docstring to be an
30+
executable statement if it appeared after line 1 in the file, but not
31+
executable if it was the first line. Now module docstrings are never counted
32+
as executable statements. This can change coverage.py's count of the number
33+
of statements in a file, which can slightly change the coverage percentage
34+
reported.
35+
2936
- In the HTML report, the filter term and "hide covered" checkbox settings are
3037
remembered between viewings, thanks to `Daniel Diniz <pull 1776_>`_.
3138

tests/test_parser.py

+14
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,20 @@ def bar(self):
165165
assert expected_arcs == parser.arcs()
166166
assert expected_exits == parser.exit_counts()
167167

168+
def test_module_docstrings(self) -> None:
169+
parser = self.parse_text("""\
170+
'''The docstring on line 1'''
171+
a = 2
172+
""")
173+
assert {2} == parser.statements
174+
175+
parser = self.parse_text("""\
176+
# Docstring is not line 1
177+
'''The docstring on line 2'''
178+
a = 3
179+
""")
180+
assert {3} == parser.statements
181+
168182
def test_fuzzed_double_parse(self) -> None:
169183
# https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=50381
170184
# The second parse used to raise `TypeError: 'NoneType' object is not iterable`

tests/test_report.py

+28
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,34 @@ def not_covered(n):
668668
assert "not_covered.py 3 3 0.000000%" in report
669669
assert "TOTAL 3 3 0.000000%" in report
670670

671+
def test_report_module_docstrings(self) -> None:
672+
self.make_file("main.py", """\
673+
# Line 1
674+
'''Line 2 docstring.'''
675+
import other
676+
a = 4
677+
""")
678+
self.make_file("other.py", """\
679+
'''Line 1'''
680+
a = 2
681+
""")
682+
cov = coverage.Coverage()
683+
self.start_import_stop(cov, "main")
684+
report = self.get_report(cov)
685+
686+
# Name Stmts Miss Cover
687+
# ------------------------------
688+
# main.py 2 0 100%
689+
# other.py 1 0 100%
690+
# ------------------------------
691+
# TOTAL 3 0 100%
692+
693+
assert self.line_count(report) == 6, report
694+
squeezed = self.squeezed_lines(report)
695+
assert squeezed[2] == "main.py 2 0 100%"
696+
assert squeezed[3] == "other.py 1 0 100%"
697+
assert squeezed[5] == "TOTAL 3 0 100%"
698+
671699
def test_dotpy_not_python(self) -> None:
672700
# We run a .py file, and when reporting, we can't parse it as Python.
673701
# We should get an error message in the report.

0 commit comments

Comments
 (0)