Coverage for tests / test_report.py: 100.000%
523 statements
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000
1# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt
4"""Test text-based summary reporting for coverage.py"""
6from __future__ import annotations 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
8import glob 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
9import io 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
10import math 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
11import os 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
12import os.path 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
13import py_compile 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
14import re 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
17import pytest 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
19import coverage 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
20from coverage import env 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
21from coverage.control import Coverage 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
22from coverage.data import CoverageData 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
23from coverage.exceptions import ConfigError, NoDataError, NotPython 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
24from coverage.files import abs_file 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
25from coverage.report import SummaryReporter 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
26from coverage.types import TConfigValueIn 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
28from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
29from tests.helpers import assert_coverage_warnings 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
32class SummaryTest(UsingModulesMixin, CoverageTest): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
33 """Tests of the text summary reporting for coverage.py."""
35 def make_mycode(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
36 """Make the mycode.py file when needed."""
37 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
38 "mycode.py",
39 """\
40 import covmod1
41 import covmodzip1
42 a = 1
43 print('done')
44 """,
45 )
47 def test_report(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
48 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
49 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
50 self.start_import_stop(cov, "mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
51 assert self.stdout() == "done\n" 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPv3fQwRxXgSyTzhUAVBYiCDj
52 report = self.get_report(cov) 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPv3fQwRxXgSyTzhUAVBYiCDj
54 # Name Stmts Miss Cover
55 # ------------------------------------------------------------------
56 # c:/ned/coverage/tests/modules/covmod1.py 2 0 100%
57 # c:/ned/coverage/tests/zipmods.zip/covmodzip1.py 2 0 100%
58 # mycode.py 4 0 100%
59 # ------------------------------------------------------------------
60 # TOTAL 8 0 100%
62 assert "/coverage/__init__/" not in report 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPv3fQwRxXgSyTzhUAVBYiCDj
63 assert "/tests/modules/covmod1.py " in report 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPv3fQwRxXgSyTzhUAVBYiCDj
64 assert "/tests/zipmods.zip/covmodzip1.py " in report 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPv3fQwRxXgSyTzhUAVBYiCDj
65 assert "mycode.py " in report 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPv3fQwRxXgSyTzhUAVBYiCDj
66 assert self.last_line_squeezed(report) == "TOTAL 8 0 100%" 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPv3fQwRxXgSyTzhUAVBYiCDj
68 def test_report_just_one(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
69 # Try reporting just one module
70 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
71 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
72 self.start_import_stop(cov, "mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
73 report = self.get_report(cov, morfs=["mycode.py"]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
75 # Name Stmts Miss Cover
76 # -------------------------------
77 # mycode.py 4 0 100%
78 # -------------------------------
79 # TOTAL 4 0 100%
80 assert self.line_count(report) == 5 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
81 assert "/coverage/" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
82 assert "/tests/modules/covmod1.py " not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
83 assert "/tests/zipmods.zip/covmodzip1.py " not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
84 assert "mycode.py " in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
85 assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
87 def test_report_wildcard(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
88 # Try reporting using wildcards to get the modules.
89 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
90 self.add_test_modules_to_pythonpath() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
91 # Wildcard is handled by shell or cmdline.py, so use real commands
92 self.run_command("coverage run mycode.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
93 report = self.report_from_command("coverage report my*.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
95 # Name Stmts Miss Cover
96 # -------------------------------
97 # mycode.py 4 0 100%
98 # -------------------------------
99 # TOTAL 4 0 100%
101 assert self.line_count(report) == 5 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
102 assert "/coverage/" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
103 assert "/tests/modules/covmod1.py " not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
104 assert "/tests/zipmods.zip/covmodzip1.py " not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
105 assert "mycode.py " in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
106 assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
108 def test_report_omitting(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
109 # Try reporting while omitting some modules
110 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
111 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
112 self.start_import_stop(cov, "mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
113 report = self.get_report(cov, omit=[f"{TESTS_DIR}/*", "*/site-packages/*"]) 1EkFlaGmHn0bIoJpcKqLrdMsNteOuPvfQwRxgSyTz4hUAVBiCDj
115 # Name Stmts Miss Cover
116 # -------------------------------
117 # mycode.py 4 0 100%
118 # -------------------------------
119 # TOTAL 4 0 100%
121 assert self.line_count(report) == 5 1EkFlaGmHn0bIoJpcKqLrdMsNteOuPvfQwRxgSyTz4hUAVBiCDj
122 assert "/coverage/" not in report 1EkFlaGmHn0bIoJpcKqLrdMsNteOuPvfQwRxgSyTz4hUAVBiCDj
123 assert "/tests/modules/covmod1.py " not in report 1EkFlaGmHn0bIoJpcKqLrdMsNteOuPvfQwRxgSyTz4hUAVBiCDj
124 assert "/tests/zipmods.zip/covmodzip1.py " not in report 1EkFlaGmHn0bIoJpcKqLrdMsNteOuPvfQwRxgSyTz4hUAVBiCDj
125 assert "mycode.py " in report 1EkFlaGmHn0bIoJpcKqLrdMsNteOuPvfQwRxgSyTz4hUAVBiCDj
126 assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" 1EkFlaGmHn0bIoJpcKqLrdMsNteOuPvfQwRxgSyTz4hUAVBiCDj
128 def test_report_including(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
129 # Try reporting while including some modules
130 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
131 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
132 self.start_import_stop(cov, "mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
133 report = self.get_report(cov, include=["mycode*"]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
135 # Name Stmts Miss Cover
136 # -------------------------------
137 # mycode.py 4 0 100%
138 # -------------------------------
139 # TOTAL 4 0 100%
141 assert self.line_count(report) == 5 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
142 assert "/coverage/" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
143 assert "/tests/modules/covmod1.py " not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
144 assert "/tests/zipmods.zip/covmodzip1.py " not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
145 assert "mycode.py " in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
146 assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
148 def test_report_include_relative_files_and_path(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
149 """
150 Test that when relative_files is True and a relative path to a module
151 is included, coverage is reported for the module.
153 Ref: https://github.com/coveragepy/coveragepy/issues/1604
154 """
155 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
156 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
157 ".coveragerc",
158 """\
159 [run]
160 relative_files = true
161 """,
162 )
163 self.make_file("submodule/mycode.py", "import mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
165 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
166 self.start_import_stop(cov, "submodule/mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
167 report = self.get_report(cov, include="submodule/mycode.py") 1EkFlaGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
169 # Name Stmts Miss Cover
170 # ---------------------------------------
171 # submodule/mycode.py 1 0 100%
172 # ---------------------------------------
173 # TOTAL 1 0 100%
175 assert "submodule/mycode.py " in report 1EkFlaGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
176 assert self.last_line_squeezed(report) == "TOTAL 1 0 100%" 1EkFlaGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
178 def test_report_include_relative_files_and_wildcard_path(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
179 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
180 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
181 ".coveragerc",
182 """\
183 [run]
184 relative_files = true
185 """,
186 )
187 self.make_file("submodule/mycode.py", "import nested.submodule.mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
188 self.make_file("nested/submodule/mycode.py", "import mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
190 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
191 self.start_import_stop(cov, "submodule/mycode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
192 report = self.get_report(cov, include="*/submodule/mycode.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
194 # Name Stmts Miss Cover
195 # -------------------------------------------------
196 # nested/submodule/mycode.py 1 0 100%
197 # submodule/mycode.py 1 0 100%
198 # -------------------------------------------------
199 # TOTAL 2 0 100%
201 reported_files = [line.split()[0] for line in report.splitlines()[2:4]] 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
202 assert reported_files == [ 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
203 "nested/submodule/mycode.py",
204 "submodule/mycode.py",
205 ]
207 def test_omit_files_here(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
208 # https://github.com/coveragepy/coveragepy/issues/1407
209 self.make_file("foo.py", "") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
210 self.make_file("bar/bar.py", "") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
211 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
212 "tests/test_baz.py",
213 """\
214 def test_foo():
215 assert True
216 test_foo()
217 """,
218 )
219 self.run_command("coverage run --source=. --omit='./*.py' -m tests.test_baz") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
220 report = self.report_from_command("coverage report") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
222 # Name Stmts Miss Cover
223 # ---------------------------------------
224 # tests/test_baz.py 3 0 100%
225 # ---------------------------------------
226 # TOTAL 3 0 100%
228 assert self.line_count(report) == 5 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
229 assert "foo" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
230 assert "bar" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
231 assert "tests/test_baz.py" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
232 assert self.last_line_squeezed(report) == "TOTAL 3 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
234 def test_run_source_vs_report_include(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
235 # https://github.com/coveragepy/coveragepy/issues/621
236 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
237 ".coveragerc",
238 """\
239 [run]
240 source = .
242 [report]
243 include = mod/*,tests/*
244 """,
245 )
246 # It should be OK to use that configuration.
247 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
248 with self.assert_warnings(cov, []): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
249 with cov.collect(): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
250 pass 1klamnbopcqrdsteuvfwxgyzhABiCDj
252 def test_run_omit_vs_report_omit(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
253 # https://github.com/coveragepy/coveragepy/issues/622
254 # report:omit shouldn't clobber run:omit.
255 self.make_mycode() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
256 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
257 ".coveragerc",
258 """\
259 [run]
260 omit = */covmodzip1.py
262 [report]
263 omit = */covmod1.py
264 """,
265 )
266 self.add_test_modules_to_pythonpath() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
267 self.run_command("coverage run mycode.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
269 # Read the data written, to see that the right files have been omitted from running.
270 covdata = CoverageData() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
271 covdata.read() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
272 files = [os.path.basename(p) for p in covdata.measured_files()] 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
273 assert "covmod1.py" in files 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
274 assert "covmodzip1.py" not in files 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
276 def test_report_branches(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
277 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
278 "mybranch.py",
279 """\
280 def branch(x):
281 if x:
282 print("x")
283 return x
284 branch(1)
285 """,
286 )
287 cov = coverage.Coverage(source=["."], branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
288 self.start_import_stop(cov, "mybranch") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
289 assert self.stdout() == "x\n" 1EkFlaGmHnbIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
290 report = self.get_report(cov) 1EkFlaGmHnbIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
292 # Name Stmts Miss Branch BrPart Cover
293 # -----------------------------------------------
294 # mybranch.py 5 0 2 1 86%
295 # -----------------------------------------------
296 # TOTAL 5 0 2 1 86%
297 assert self.line_count(report) == 5 1EkFlaGmHnbIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
298 assert "mybranch.py " in report 1EkFlaGmHnbIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
299 assert self.last_line_squeezed(report) == "TOTAL 5 0 2 1 86%" 1EkFlaGmHnbIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
301 def test_report_show_missing(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
302 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
303 "mymissing.py",
304 """\
305 def missing(x, y):
306 if x:
307 print("x")
308 return x
309 if y:
310 print("y")
311 try:
312 print("z")
313 1/0
314 print("Never!")
315 except ZeroDivisionError:
316 pass
317 return x
318 missing(0, 1)
319 """,
320 )
321 cov = coverage.Coverage(source=["."]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
322 self.start_import_stop(cov, "mymissing") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
323 assert self.stdout() == "y\nz\n" 1EkFl2aGmHnbIoJpWcKqLrdMsNtZeOuPvfQwRxXgSyTz4hUAVBYiCDj
324 report = self.get_report(cov, show_missing=True) 1EkFl2aGmHnbIoJpWcKqLrdMsNtZeOuPvfQwRxXgSyTz4hUAVBYiCDj
326 # Name Stmts Miss Cover Missing
327 # --------------------------------------------
328 # mymissing.py 14 3 79% 3-4, 10
329 # --------------------------------------------
330 # TOTAL 14 3 79%
332 assert self.line_count(report) == 5 1EkFl2aGmHnbIoJpWcKqLrdMsNtZeOuPvfQwRxXgSyTz4hUAVBYiCDj
333 squeezed = self.squeezed_lines(report) 1EkFl2aGmHnbIoJpWcKqLrdMsNtZeOuPvfQwRxXgSyTz4hUAVBYiCDj
334 assert squeezed[2] == "mymissing.py 14 3 79% 3-4, 10" 1EkFl2aGmHnbIoJpWcKqLrdMsNtZeOuPvfQwRxXgSyTz4hUAVBYiCDj
335 assert squeezed[4] == "TOTAL 14 3 79%" 1EkFl2aGmHnbIoJpWcKqLrdMsNtZeOuPvfQwRxXgSyTz4hUAVBYiCDj
337 def test_report_show_missing_branches(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
338 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
339 "mybranch.py",
340 """\
341 def branch(x, y):
342 if x:
343 print("x")
344 if y:
345 print("y")
346 branch(1, 1)
347 """,
348 )
349 cov = coverage.Coverage(branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
350 self.start_import_stop(cov, "mybranch") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
351 assert self.stdout() == "x\ny\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
352 report = self.get_report(cov, show_missing=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
354 # Name Stmts Miss Branch BrPart Cover Missing
355 # ----------------------------------------------------------
356 # mybranch.py 6 0 4 2 80% 2->4, 4->exit
357 # ----------------------------------------------------------
358 # TOTAL 6 0 4 2 80%
360 assert self.line_count(report) == 5 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
361 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
362 assert squeezed[2] == "mybranch.py 6 0 4 2 80% 2->4, 4->exit" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
363 assert squeezed[4] == "TOTAL 6 0 4 2 80%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
365 def test_report_show_missing_branches_and_lines(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
366 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
367 "main.py",
368 """\
369 import mybranch
370 """,
371 )
372 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
373 "mybranch.py",
374 """\
375 def branch(x, y, z):
376 if x:
377 print("x")
378 if y:
379 print("y")
380 if z:
381 if x and y:
382 print("z")
383 return x
384 branch(1, 1, 0)
385 """,
386 )
387 cov = coverage.Coverage(branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
388 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
389 assert self.stdout() == "x\ny\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
390 report_lines = self.get_report(cov, squeeze=False, show_missing=True).splitlines() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
392 expected = [ 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
393 "Name Stmts Miss Branch BrPart Cover Missing",
394 "---------------------------------------------------------",
395 "main.py 1 0 0 0 100%",
396 "mybranch.py 10 2 8 3 61% 2->4, 4->6, 7-8",
397 "---------------------------------------------------------",
398 "TOTAL 11 2 8 3 63%",
399 ]
400 assert expected == report_lines 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
402 def test_report_skip_covered_no_branches(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
403 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
404 "main.py",
405 """\
406 import not_covered
408 def normal():
409 print("z")
410 normal()
411 """,
412 )
413 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
414 "not_covered.py",
415 """\
416 def not_covered():
417 print("n")
418 """,
419 )
420 # --fail-under is handled by cmdline.py, use real commands.
421 out = self.run_command("coverage run main.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
422 assert out == "z\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
423 report = self.report_from_command("coverage report --skip-covered --fail-under=70") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
425 # Name Stmts Miss Cover
426 # ------------------------------------
427 # not_covered.py 2 1 50%
428 # ------------------------------------
429 # TOTAL 6 1 83%
430 #
431 # 1 file skipped due to complete coverage.
433 assert self.line_count(report) == 7, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
434 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
435 assert squeezed[2] == "not_covered.py 2 1 50%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
436 assert squeezed[4] == "TOTAL 6 1 83%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
437 assert squeezed[6] == "1 file skipped due to complete coverage." 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
438 assert self.last_command_status == 0 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
440 def test_report_skip_covered_branches(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
441 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
442 "main.py",
443 """\
444 import not_covered, covered
446 def normal(z):
447 if z:
448 print("z")
449 normal(True)
450 normal(False)
451 """,
452 )
453 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
454 "not_covered.py",
455 """\
456 def not_covered(n):
457 if n:
458 print("n")
459 not_covered(True)
460 """,
461 )
462 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
463 "covered.py",
464 """\
465 def foo():
466 pass
467 foo()
468 """,
469 )
470 cov = coverage.Coverage(branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
471 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
472 assert self.stdout() == "n\nz\n" 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPvfQwRxXgSyTz4hUAVBYiCDj
473 report = self.get_report(cov, skip_covered=True) 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPvfQwRxXgSyTz4hUAVBYiCDj
475 # Name Stmts Miss Branch BrPart Cover
476 # --------------------------------------------------
477 # not_covered.py 4 0 2 1 83%
478 # --------------------------------------------------
479 # TOTAL 13 0 4 1 94%
480 #
481 # 2 files skipped due to complete coverage.
483 assert self.line_count(report) == 7, report 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPvfQwRxXgSyTz4hUAVBYiCDj
484 squeezed = self.squeezed_lines(report) 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPvfQwRxXgSyTz4hUAVBYiCDj
485 assert squeezed[2] == "not_covered.py 4 0 2 1 83%" 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPvfQwRxXgSyTz4hUAVBYiCDj
486 assert squeezed[4] == "TOTAL 13 0 4 1 94%" 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPvfQwRxXgSyTz4hUAVBYiCDj
487 assert squeezed[6] == "2 files skipped due to complete coverage." 1EkFlaGmHnbIoJpWcKqLrdMsNteOuPvfQwRxXgSyTz4hUAVBYiCDj
489 def test_report_skip_covered_branches_with_totals(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
490 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
491 "main.py",
492 """\
493 import not_covered
494 import also_not_run
496 def normal(z):
497 if z:
498 print("z")
499 normal(True)
500 normal(False)
501 """,
502 )
503 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
504 "not_covered.py",
505 """\
506 def not_covered(n):
507 if n:
508 print("n")
509 not_covered(True)
510 """,
511 )
512 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
513 "also_not_run.py",
514 """\
515 def does_not_appear_in_this_film(ni):
516 print("Ni!")
517 """,
518 )
519 cov = coverage.Coverage(branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
520 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
521 assert self.stdout() == "n\nz\n" 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
522 report = self.get_report(cov, skip_covered=True) 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
524 # Name Stmts Miss Branch BrPart Cover
525 # --------------------------------------------------
526 # also_not_run.py 2 1 0 0 50%
527 # not_covered.py 4 0 2 1 83%
528 # --------------------------------------------------
529 # TOTAL 13 1 4 1 88%
530 #
531 # 1 file skipped due to complete coverage.
533 assert self.line_count(report) == 8, report 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
534 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
535 assert squeezed[2] == "also_not_run.py 2 1 0 0 50%" 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
536 assert squeezed[3] == "not_covered.py 4 0 2 1 83%" 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
537 assert squeezed[5] == "TOTAL 13 1 4 1 88%" 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
538 assert squeezed[7] == "1 file skipped due to complete coverage." 1EkFl2aGmHn0bIoJpcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
540 def test_report_skip_covered_all_files_covered(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
541 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
542 "main.py",
543 """\
544 def foo():
545 pass
546 foo()
547 """,
548 )
549 cov = coverage.Coverage(source=["."], branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
550 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
551 assert self.stdout() == "" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
552 report = self.get_report(cov, skip_covered=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
554 # Name Stmts Miss Branch BrPart Cover
555 # -----------------------------------------
556 # TOTAL 3 0 0 0 100%
557 #
558 # 1 file skipped due to complete coverage.
560 assert self.line_count(report) == 5, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
561 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
562 assert squeezed[4] == "1 file skipped due to complete coverage." 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
564 report = self.get_report(cov, squeeze=False, skip_covered=True, output_format="markdown") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
566 # | Name | Stmts | Miss | Branch | BrPart | Cover |
567 # |---------- | -------: | -------: | -------: | -------: | -------: |
568 # | **TOTAL** | **3** | **0** | **0** | **0** | **100%** |
569 #
570 # 1 file skipped due to complete coverage.
572 assert self.line_count(report) == 5, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
573 assert report.split("\n")[0] == ( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
574 "| Name | Stmts | Miss | Branch | BrPart | Cover |"
575 )
576 assert report.split("\n")[1] == ( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
577 "|---------- | -------: | -------: | -------: | -------: | -------: |"
578 )
579 assert report.split("\n")[2] == ( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
580 "| **TOTAL** | **3** | **0** | **0** | **0** | **100%** |"
581 )
582 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
583 assert squeezed[4] == "1 file skipped due to complete coverage." 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
585 total = self.get_report(cov, output_format="total", skip_covered=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
586 assert total == "100\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPvfQwRxXgSyTzhUAVBYiCDj
588 def test_report_skip_covered_longfilename(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
589 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
590 "long_______________filename.py",
591 """\
592 def foo():
593 pass
594 foo()
595 """,
596 )
597 cov = coverage.Coverage(source=["."], branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
598 self.start_import_stop(cov, "long_______________filename") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
599 assert self.stdout() == "" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
600 report = self.get_report(cov, squeeze=False, skip_covered=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
602 # Name Stmts Miss Branch BrPart Cover
603 # -----------------------------------------
604 # TOTAL 3 0 0 0 100%
605 #
606 # 1 file skipped due to complete coverage.
608 assert self.line_count(report) == 5, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
609 lines = self.report_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
610 assert lines[0] == "Name Stmts Miss Branch BrPart Cover" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
611 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
612 assert squeezed[4] == "1 file skipped due to complete coverage." 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
614 def test_report_skip_covered_no_data(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
615 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
616 cov.load() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
617 with pytest.raises(NoDataError, match="No data to report."): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
618 self.get_report(cov, skip_covered=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
619 self.assert_doesnt_exist(".coverage") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
621 def test_report_skip_empty(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
622 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
623 "main.py",
624 """\
625 import submodule
627 def normal():
628 print("z")
629 normal()
630 """,
631 )
632 self.make_file("submodule/__init__.py", "") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
633 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
634 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
635 assert self.stdout() == "z\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
636 report = self.get_report(cov, skip_empty=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
638 # Name Stmts Miss Cover
639 # ------------------------------------
640 # main.py 4 0 100%
641 # ------------------------------------
642 # TOTAL 4 0 100%
643 #
644 # 1 empty file skipped.
646 assert self.line_count(report) == 7, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
647 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
648 assert squeezed[2] == "main.py 4 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
649 assert squeezed[4] == "TOTAL 4 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
650 assert squeezed[6] == "1 empty file skipped." 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTzhUAVBYiCDj
652 def test_report_skip_empty_no_data(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
653 self.make_file("__init__.py", "") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
654 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
655 self.start_import_stop(cov, "__init__") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
656 assert self.stdout() == "" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
657 report = self.get_report(cov, skip_empty=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
659 # Name Stmts Miss Cover
660 # ------------------------------------
661 # TOTAL 0 0 100%
662 #
663 # 1 empty file skipped.
665 assert self.line_count(report) == 5, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
666 assert report.split("\n")[2] == "TOTAL 0 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
667 assert report.split("\n")[4] == "1 empty file skipped." 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxgSyTz4hUAVBYiCDj
669 def test_report_precision(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
670 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
671 ".coveragerc",
672 """\
673 [report]
674 precision = 3
675 omit = */site-packages/*
676 """,
677 )
678 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
679 "main.py",
680 """\
681 import not_covered, covered
683 def normal(z):
684 if z:
685 print("z")
686 normal(True)
687 normal(False)
688 """,
689 )
690 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
691 "not_covered.py",
692 """\
693 def not_covered(n):
694 if n:
695 print("n")
696 not_covered(True)
697 """,
698 )
699 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
700 "covered.py",
701 """\
702 def foo():
703 pass
704 foo()
705 """,
706 )
707 cov = coverage.Coverage(branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
708 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
709 assert self.stdout() == "n\nz\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
710 report = self.get_report(cov, squeeze=False) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
712 # Name Stmts Miss Branch BrPart Cover
713 # ------------------------------------------------------
714 # covered.py 3 0 0 0 100.000%
715 # main.py 6 0 2 0 100.000%
716 # not_covered.py 4 0 2 1 83.333%
717 # ------------------------------------------------------
718 # TOTAL 13 0 4 1 94.118%
720 assert self.line_count(report) == 7, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
721 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
722 assert squeezed[2] == "covered.py 3 0 0 0 100.000%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
723 assert squeezed[4] == "not_covered.py 4 0 2 1 83.333%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
724 assert squeezed[6] == "TOTAL 13 0 4 1 94.118%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
726 def test_report_precision_all_zero(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
727 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
728 "not_covered.py",
729 """\
730 def not_covered(n):
731 if n:
732 print("n")
733 """,
734 )
735 self.make_file("empty.py", "") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
736 cov = coverage.Coverage(source=["."]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
737 self.start_import_stop(cov, "empty") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
738 report = self.get_report(cov, precision=6, squeeze=False) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
740 # Name Stmts Miss Cover
741 # -----------------------------------------
742 # empty.py 0 0 100.000000%
743 # not_covered.py 3 3 0.000000%
744 # -----------------------------------------
745 # TOTAL 3 3 0.000000%
747 assert self.line_count(report) == 6, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
748 assert "empty.py 0 0 100.000000%" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
749 assert "not_covered.py 3 3 0.000000%" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
750 assert "TOTAL 3 3 0.000000%" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
752 def test_report_module_docstrings(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
753 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
754 "main.py",
755 """\
756 # Line 1
757 '''Line 2 docstring.'''
758 import other
759 a = 4
760 """,
761 )
762 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
763 "other.py",
764 """\
765 '''Line 1'''
766 a = 2
767 """,
768 )
769 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
770 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
771 report = self.get_report(cov) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
773 # Name Stmts Miss Cover
774 # ------------------------------
775 # main.py 2 0 100%
776 # other.py 1 0 100%
777 # ------------------------------
778 # TOTAL 3 0 100%
780 assert self.line_count(report) == 6, report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
781 squeezed = self.squeezed_lines(report) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
782 assert squeezed[2] == "main.py 2 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
783 assert squeezed[3] == "other.py 1 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
784 assert squeezed[5] == "TOTAL 3 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
786 def test_dotpy_not_python(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
787 # We run a .py file, and when reporting, we can't parse it as Python.
788 # We should get an error message in the report.
790 self.make_data_file(lines={"mycode.py": [1]}) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
791 self.make_file("mycode.py", "This isn't python at all!") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
792 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
793 cov.load() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
794 msg = r"Couldn't parse '.*[/\\]mycode.py' as Python source: '.*' at line 1" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
795 with pytest.raises(NotPython, match=msg): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
796 self.get_report(cov, morfs=["mycode.py"]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
798 def test_accented_directory(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
799 # Make a file with a non-ascii character in the directory name.
800 self.make_file("\xe2/accented.py", "print('accented')") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
801 self.make_data_file(lines={abs_file("\xe2/accented.py"): [1]}) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
802 report_expected = ( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
803 "Name Stmts Miss Cover\n"
804 + "-----------------------------------\n"
805 + "\xe2/accented.py 1 0 100%\n"
806 + "-----------------------------------\n"
807 + "TOTAL 1 0 100%\n"
808 )
809 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
810 cov.load() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
811 output = self.get_report(cov, squeeze=False) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
812 assert output == report_expected 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
814 def test_accenteddotpy_not_python(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
815 # We run a .py file with a non-ascii name, and when reporting, we can't
816 # parse it as Python. We should get an error message in the report.
818 self.make_data_file(lines={"accented\xe2.py": [1]}) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
819 self.make_file("accented\xe2.py", "This isn't python at all!") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
820 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
821 cov.load() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
822 msg = r"Couldn't parse '.*[/\\]accented\xe2.py' as Python source: '.*' at line 1" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
823 with pytest.raises(NotPython, match=msg): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
824 self.get_report(cov, morfs=["accented\xe2.py"]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
826 @pytest.mark.parametrize("filename", ["mycode.py", "my_script"]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
827 def test_dotpy_not_python_ignored(self, filename: str) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
828 # We run a Python file, and when reporting, we can't parse it as Python,
829 # but we've said to ignore errors, so there's no error reported,
830 # though we still get a warning.
831 self.make_file(filename, "This isn't python at all! I can't cope.") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
832 self.make_data_file(lines={filename: [1]}) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
833 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
834 cov.load() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
835 with pytest.raises(NoDataError, match="No data to report."): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
836 with pytest.warns(Warning) as warns: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
837 self.get_report(cov, morfs=[filename], ignore_errors=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
838 assert_coverage_warnings( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
839 warns,
840 re.compile(rf"Couldn't parse Python file '.*[/\\]{filename}' \(couldnt-parse\)"),
841 )
843 def test_dothtml_not_python(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
844 # We run a .html file, and when reporting, we can't parse it as
845 # Python. Since it wasn't .py, no error is reported.
847 # Pretend to run an html file.
848 self.make_file("mycode.html", "<h1>This isn't python at all!</h1>") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
849 self.make_data_file(lines={"mycode.html": [1]}) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
850 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
851 cov.load() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
852 with pytest.raises(NoDataError, match="No data to report."): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
853 self.get_report(cov, morfs=["mycode.html"]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
855 def test_report_no_extension(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
856 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
857 "xxx",
858 """\
859 # This is a python file though it doesn't look like it, like a main script.
860 a = b = c = d = 0
861 a = 3
862 b = 4
863 if not b:
864 c = 6
865 d = 7
866 print(f"xxx: {a} {b} {c} {d}")
867 """,
868 )
869 self.make_data_file(lines={abs_file("xxx"): [2, 3, 4, 5, 7, 8]}) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
870 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
871 cov.load() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
872 report = self.get_report(cov) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
873 assert self.last_line_squeezed(report) == "TOTAL 7 1 86%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
875 def test_report_with_chdir(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
876 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
877 "chdir.py",
878 """\
879 import os
880 print("Line One")
881 os.chdir("subdir")
882 print("Line Two")
883 print(open("something", encoding="utf-8").read())
884 """,
885 )
886 self.make_file("subdir/something", "hello") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
887 out = self.run_command("coverage run --source=. chdir.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
888 assert out == "Line One\nLine Two\nhello\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
889 report = self.report_from_command("coverage report") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
890 assert self.last_line_squeezed(report) == "TOTAL 5 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
891 report = self.report_from_command("coverage report --format=markdown") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
892 assert self.last_line_squeezed(report) == "| **TOTAL** | **5** | **0** | **100%** |" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
894 def test_bug_156_file_not_run_should_be_zero(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
895 # https://github.com/coveragepy/coveragepy/issues/156
896 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
897 "mybranch.py",
898 """\
899 def branch(x):
900 if x:
901 print("x")
902 return x
903 branch(1)
904 """,
905 )
906 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
907 "main.py",
908 """\
909 print("y")
910 """,
911 )
912 cov = coverage.Coverage(branch=True, source=["."]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
913 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
914 report = self.get_report(cov).splitlines() 1EkFl2aGmHnbIoJpcKqLr1dMsNteOuPv3fQwRxXgSyTz4hUAVBYiCDj
915 assert "mybranch.py 5 5 2 0 0%" in report 1EkFl2aGmHnbIoJpcKqLr1dMsNteOuPv3fQwRxXgSyTz4hUAVBYiCDj
917 def run_TheCode_and_report_it(self) -> str: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
918 """A helper for the next few tests."""
919 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
920 self.start_import_stop(cov, "TheCode") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
921 return self.get_report(cov) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
923 def test_bug_203_mixed_case_listed_twice_with_rc(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
924 self.make_file("TheCode.py", "a = 1\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
925 self.make_file(".coveragerc", "[run]\nsource = .\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
927 report = self.run_TheCode_and_report_it() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
928 assert "TheCode" in report 1EkFlaGmHn0bIoJpWcKqLrdMsNtZeOuPvfQwRxgSyTz4hUAVBYiCDj
929 assert "thecode" not in report 1EkFlaGmHn0bIoJpWcKqLrdMsNtZeOuPvfQwRxgSyTz4hUAVBYiCDj
931 def test_bug_203_mixed_case_listed_twice(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
932 self.make_file("TheCode.py", "a = 1\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
934 report = self.run_TheCode_and_report_it() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
936 assert "TheCode" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
937 assert "thecode" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
939 @pytest.mark.skipif(not env.WINDOWS, reason=".pyw files are only on Windows.") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
940 def test_pyw_files(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
941 # https://github.com/coveragepy/coveragepy/issues/261
942 self.make_file( 12a0bWc1dZe3f5Xg64h7Yi8j
943 "start.pyw",
944 """\
945 import mod
946 print("In start.pyw")
947 """,
948 )
949 self.make_file( 12a0bWc1dZe3f5Xg64h7Yi8j
950 "mod.pyw",
951 """\
952 print("In mod.pyw")
953 """,
954 )
955 cov = coverage.Coverage() 12a0bWc1dZe3f5Xg64h7Yi8j
956 # start_import_stop can't import the .pyw file, so use the long form.
957 with cov.collect(): 12a0bWc1dZe3f5Xg64h7Yi8j
958 import start # pylint: disable=import-error, unused-import 1abcdefghij
960 report = self.get_report(cov) 12a0bWc1dZe3fXghYij
961 assert "NoSource" not in report 12a0bWc1dZe3fXghYij
962 report_lines = report.splitlines() 12a0bWc1dZe3fXghYij
963 assert "start.pyw 2 0 100%" in report_lines 12a0bWc1dZe3fXghYij
964 assert "mod.pyw 1 0 100%" in report_lines 12a0bWc1dZe3fXghYij
966 def test_tracing_pyc_file(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
967 # Create two Python files.
968 self.make_file("mod.py", "a = 1\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
969 self.make_file("main.py", "import mod\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
971 # Make one into a .pyc.
972 py_compile.compile("mod.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
974 # Run the program.
975 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
976 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
978 report_lines = self.get_report(cov).splitlines() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
979 assert "mod.py 1 0 100%" in report_lines 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
980 report = self.get_report(cov, squeeze=False, output_format="markdown") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
981 assert report.split("\n")[3] == "| mod.py | 1 | 0 | 100% |" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
982 assert report.split("\n")[4] == "| **TOTAL** | **2** | **0** | **100%** |" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
984 def test_missing_py_file_during_run(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
985 # Create two Python files.
986 self.make_file("mod.py", "a = 1\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
987 self.make_file("main.py", "import mod\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
989 # Make one into a .pyc, and remove the .py.
990 py_compile.compile("mod.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
991 os.remove("mod.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
993 # Python 3 puts the .pyc files in a __pycache__ directory, and will
994 # not import from there without source. It will import a .pyc from
995 # the source location though.
996 pycs = glob.glob("__pycache__/mod.*.pyc") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
997 assert len(pycs) == 1 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
998 os.rename(pycs[0], "mod.pyc") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1000 # Run the program.
1001 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1002 self.start_import_stop(cov, "main") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1004 # Put back the missing Python file.
1005 self.make_file("mod.py", "a = 1\n") 1EkFl2aGmHn0bIoJpcKqLr1dMsNteOuPv3fQwRxXgSyTz4hUAVBYiCDj
1006 report = self.get_report(cov).splitlines() 1EkFl2aGmHn0bIoJpcKqLr1dMsNteOuPv3fQwRxXgSyTz4hUAVBYiCDj
1007 assert "mod.py 1 0 100%" in report 1EkFl2aGmHn0bIoJpcKqLr1dMsNteOuPv3fQwRxXgSyTz4hUAVBYiCDj
1009 def test_empty_files(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1010 # Shows that empty files like __init__.py are listed as having zero
1011 # statements, not one statement.
1012 cov = coverage.Coverage(branch=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1013 with cov.collect(): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1014 import usepkgs # pylint: disable=import-error, unused-import 1klamnbopcqrdsteuvfwxgyzhABiCDj
1015 report = self.get_report(cov) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1016 assert "tests/modules/pkg1/__init__.py 1 0 0 0 100%" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1017 assert "tests/modules/pkg2/__init__.py 0 0 0 0 100%" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1018 report = self.get_report(cov, squeeze=False, output_format="markdown") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1019 # get_report() escapes backslash so we expect forward slash escaped
1020 # underscore
1021 assert "tests/modules/pkg1//_/_init/_/_.py " in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1022 assert "| 1 | 0 | 0 | 0 | 100% |" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1023 assert "tests/modules/pkg2//_/_init/_/_.py " in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1024 assert "| 0 | 0 | 0 | 0 | 100% |" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBiCDj
1026 def test_markdown_with_missing(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1027 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1028 "mymissing.py",
1029 """\
1030 def missing(x, y):
1031 if x:
1032 print("x")
1033 return x
1034 if y:
1035 print("y")
1036 try:
1037 print("z")
1038 1/0
1039 print("Never!")
1040 except ZeroDivisionError:
1041 pass
1042 return x
1043 missing(0, 1)
1044 """,
1045 )
1046 cov = coverage.Coverage(source=["."]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1047 self.start_import_stop(cov, "mymissing") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1048 assert self.stdout() == "y\nz\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1049 report = self.get_report(cov, squeeze=False, output_format="markdown", show_missing=True) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1051 # | Name | Stmts | Miss | Cover | Missing |
1052 # |------------- | -------: | -------: | ------: | --------: |
1053 # | mymissing.py | 14 | 3 | 79% | 3-4, 10 |
1054 # | **TOTAL** | **14** | **3** | **79%** | |
1055 assert self.line_count(report) == 4 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1056 report_lines = report.split("\n") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1057 assert report_lines[2] == "| mymissing.py | 14 | 3 | 79% | 3-4, 10 |" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1058 assert report_lines[3] == "| **TOTAL** | **14** | **3** | **79%** | |" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1060 assert self.get_report(cov, output_format="total") == "79\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1061 assert self.get_report(cov, output_format="total", precision=2) == "78.57\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1062 assert self.get_report(cov, output_format="total", precision=4) == "78.5714\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1064 def test_bug_1524(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1065 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1066 "bug1524.py",
1067 """\
1068 class Mine:
1069 @property
1070 def thing(self) -> int:
1071 return 17
1073 print(Mine().thing)
1074 """,
1075 )
1076 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1077 self.start_import_stop(cov, "bug1524") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1078 assert self.stdout() == "17\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1079 report = self.get_report(cov) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1080 report_lines = report.splitlines() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1081 assert report_lines[2] == "bug1524.py 5 0 100%" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1084class ReportingReturnValueTest(CoverageTest): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1085 """Tests of reporting functions returning values."""
1087 def run_coverage(self) -> Coverage: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1088 """Run coverage on doit.py and return the coverage object."""
1089 self.make_file( 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1090 "doit.py",
1091 """\
1092 a = 1
1093 b = 2
1094 c = 3
1095 d = 4
1096 if a > 10:
1097 f = 6
1098 g = 7
1099 """,
1100 )
1102 cov = coverage.Coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1103 self.start_import_stop(cov, "doit") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1104 return cov 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1106 def test_report(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1107 cov = self.run_coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1108 val = cov.report(include="*/doit.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1109 assert math.isclose(val, 6 / 7 * 100) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1111 def test_html(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1112 cov = self.run_coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1113 val = cov.html_report(include="*/doit.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1114 assert math.isclose(val, 6 / 7 * 100) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1116 def test_xml(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1117 cov = self.run_coverage() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1118 val = cov.xml_report(include="*/doit.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1119 assert math.isclose(val, 6 / 7 * 100) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1122class SummaryReporterConfigurationTest(CoverageTest): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1123 """Tests of SummaryReporter."""
1125 def make_rigged_file(self, filename: str, stmts: int, miss: int) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1126 """Create a file that will have specific results.
1128 `stmts` and `miss` are ints, the number of statements, and
1129 missed statements that should result.
1130 """
1131 run = stmts - miss - 1 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1132 dont_run = miss 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1133 source = "" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1134 source += "a = 1\n" * run 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1135 source += "if a == 99:\n" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1136 source += " a = 2\n" * dont_run 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1137 self.make_file(filename, source) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1139 def get_summary_text(self, *options: tuple[str, TConfigValueIn]) -> str: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1140 """Get text output from the SummaryReporter.
1142 The arguments are tuples: (name, value) for Coverage.set_option.
1143 """
1144 self.make_rigged_file("file1.py", 339, 155) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1145 self.make_rigged_file("file2.py", 13, 3) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1146 self.make_rigged_file("file10.py", 234, 228) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1147 self.make_file("doit.py", "import file1, file2, file10") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1149 cov = Coverage(source=["."], omit=["doit.py"]) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1150 self.start_import_stop(cov, "doit") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1151 for name, value in options: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1152 cov.set_option(name, value) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1153 printer = SummaryReporter(cov) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1154 destination = io.StringIO() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1155 printer.report([], destination) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1156 return destination.getvalue() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1158 def test_test_data(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1159 # We use our own test files as test data. Check that our assumptions
1160 # about them are still valid. We want the three columns of numbers to
1161 # sort in three different orders.
1162 report = self.get_summary_text() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1163 # Name Stmts Miss Cover
1164 # ------------------------------
1165 # file1.py 339 155 54%
1166 # file2.py 13 3 77%
1167 # file10.py 234 228 3%
1168 # ------------------------------
1169 # TOTAL 586 386 34%
1170 lines = report.splitlines()[2:-2] 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1171 assert len(lines) == 3 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1172 nums = [list(map(int, l.replace("%", "").split()[1:])) for l in lines] 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1173 # [
1174 # [339, 155, 54],
1175 # [ 13, 3, 77],
1176 # [234, 228, 3]
1177 # ]
1178 assert nums[1][0] < nums[2][0] < nums[0][0] 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1179 assert nums[1][1] < nums[0][1] < nums[2][1] 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1180 assert nums[2][2] < nums[0][2] < nums[1][2] 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1182 def test_defaults(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1183 """Run the report with no configuration options."""
1184 report = self.get_summary_text() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1185 assert "Missing" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1186 assert "Branch" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1188 def test_print_missing(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1189 """Run the report printing the missing lines."""
1190 report = self.get_summary_text(("report:show_missing", True)) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1191 assert "Missing" in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1192 assert "Branch" not in report 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1194 def assert_ordering(self, text: str, *words: str) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1195 """Assert that the `words` appear in order in `text`."""
1196 indexes = list(map(text.find, words)) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1197 assert -1 not in indexes 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1198 msg = f"The words {words!r} don't appear in order in {text!r}" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1199 assert indexes == sorted(indexes), msg 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1201 def test_default_sort_report(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1202 # Sort the text report by the default (Name) column.
1203 report = self.get_summary_text() 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1204 self.assert_ordering(report, "file1.py", "file2.py", "file10.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1206 def test_sort_report_by_name(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1207 # Sort the text report explicitly by the Name column.
1208 report = self.get_summary_text(("report:sort", "Name")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1209 self.assert_ordering(report, "file1.py", "file2.py", "file10.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1211 def test_sort_report_by_stmts(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1212 # Sort the text report by the Stmts column.
1213 report = self.get_summary_text(("report:sort", "Stmts")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1214 self.assert_ordering(report, "file2.py", "file10.py", "file1.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1216 def test_sort_report_by_missing(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1217 # Sort the text report by the Missing column.
1218 report = self.get_summary_text(("report:sort", "Miss")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1219 self.assert_ordering(report, "file2.py", "file1.py", "file10.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1221 def test_sort_report_by_cover(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1222 # Sort the text report by the Cover column.
1223 report = self.get_summary_text(("report:sort", "Cover")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1224 self.assert_ordering(report, "file10.py", "file1.py", "file2.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1226 def test_sort_report_by_cover_plus(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1227 # Sort the text report by the Cover column, including the explicit + sign.
1228 report = self.get_summary_text(("report:sort", "+Cover")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1229 self.assert_ordering(report, "file10.py", "file1.py", "file2.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1231 def test_sort_report_by_cover_reversed(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1232 # Sort the text report by the Cover column reversed.
1233 report = self.get_summary_text(("report:sort", "-Cover")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1234 self.assert_ordering(report, "file2.py", "file1.py", "file10.py") 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOuPv3fQwRxXgSyTz4hUAVBYiCDj
1236 def test_sort_report_by_invalid_option(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1237 # Sort the text report by a nonsense column.
1238 msg = "Invalid sorting option: 'Xyzzy'" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1239 with pytest.raises(ConfigError, match=msg): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1240 self.get_summary_text(("report:sort", "Xyzzy")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1242 def test_report_with_invalid_format(self) -> None: 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1243 # Ask for an invalid format.
1244 msg = "Unknown report format choice: 'xyzzy'" 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1245 with pytest.raises(ConfigError, match=msg): 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj
1246 self.get_summary_text(("report:format", "xyzzy")) 1EkFl2aGmHn0bIoJpWcKqLr1dMsNtZeOu9Pv!3f5Qw#Rx$Xg6Sy%Tz'4h7UA(VB)Yi8CDj