Skip to content

Commit

Permalink
fix: module docstrings are never counted as statements
Browse files Browse the repository at this point in the history
  • Loading branch information
nedbat committed May 15, 2024
1 parent 96bd930 commit 81089de
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ Unreleased
- Fix: nested matches of exclude patterns could exclude too much code, as
reported in `issue 1779`_. This is now fixed.

- Changed: previously, coverage.py would consider a module docstring to be an
executable statement if it appeared after line 1 in the file, but not
executable if it was the first line. Now module docstrings are never counted
as executable statements. This can change coverage.py's count of the number
of statements in a file, which can slightly change the coverage percentage
reported.

- In the HTML report, the filter term and "hide covered" checkbox settings are
remembered between viewings, thanks to `Daniel Diniz <pull 1776_>`_.

Expand Down
14 changes: 14 additions & 0 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,20 @@ def bar(self):
assert expected_arcs == parser.arcs()
assert expected_exits == parser.exit_counts()

def test_module_docstrings(self) -> None:
parser = self.parse_text("""\
'''The docstring on line 1'''
a = 2
""")
assert {2} == parser.statements

parser = self.parse_text("""\
# Docstring is not line 1
'''The docstring on line 2'''
a = 3
""")
assert {3} == parser.statements

def test_fuzzed_double_parse(self) -> None:
# https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=50381
# The second parse used to raise `TypeError: 'NoneType' object is not iterable`
Expand Down
28 changes: 28 additions & 0 deletions tests/test_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,34 @@ def not_covered(n):
assert "not_covered.py 3 3 0.000000%" in report
assert "TOTAL 3 3 0.000000%" in report

def test_report_module_docstrings(self) -> None:
self.make_file("main.py", """\
# Line 1
'''Line 2 docstring.'''
import other
a = 4
""")
self.make_file("other.py", """\
'''Line 1'''
a = 2
""")
cov = coverage.Coverage()
self.start_import_stop(cov, "main")
report = self.get_report(cov)

# Name Stmts Miss Cover
# ------------------------------
# main.py 2 0 100%
# other.py 1 0 100%
# ------------------------------
# TOTAL 3 0 100%

assert self.line_count(report) == 6, report
squeezed = self.squeezed_lines(report)
assert squeezed[2] == "main.py 2 0 100%"
assert squeezed[3] == "other.py 1 0 100%"
assert squeezed[5] == "TOTAL 3 0 100%"

def test_dotpy_not_python(self) -> None:
# We run a .py file, and when reporting, we can't parse it as Python.
# We should get an error message in the report.
Expand Down

0 comments on commit 81089de

Please sign in to comment.