Coverage for tests / test_regions.py: 100.000%
22 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"""Tests for coverage/regions.py."""
6from __future__ import annotations 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
8import collections 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
9import textwrap 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
10from pathlib import Path 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
12import pytest 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
14from coverage.plugin import CodeRegion 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
15from coverage.regions import code_regions 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
17from tests.helpers import all_our_source_files 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
20def test_code_regions() -> None: 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
21 regions = code_regions( 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
22 textwrap.dedent("""\
23 # Numbers in this code are the line number.
24 '''Module docstring'''
26 CONST = 4
27 class MyClass:
28 class_attr = 6
30 def __init__(self):
31 self.x = 9
33 def method_a(self):
34 self.x = 12
35 def inmethod():
36 self.x = 14
37 class DeepInside:
38 def method_b():
39 self.x = 17
40 class Deeper:
41 def bb():
42 self.x = 20
43 self.y = 21
45 class InnerClass:
46 constant = 24
47 def method_c(self):
48 self.x = 26
50 def func():
51 x = 29
52 y = 30
53 def inner():
54 z = 32
55 def inner_inner():
56 w = 34
58 class InsideFunc:
59 def method_d(self):
60 self.x = 38
62 return 40
64 async def afunc():
65 x = 43
66 """)
67 )
69 F = "function" 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
70 C = "class" 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
72 assert sorted(regions) == sorted( 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
73 [
74 CodeRegion(F, "MyClass.__init__", start=8, lines={9}),
75 CodeRegion(F, "MyClass.method_a", start=11, lines={12, 13, 21}),
76 CodeRegion(F, "MyClass.method_a.inmethod", start=13, lines={14, 15, 16, 18, 19}),
77 CodeRegion(F, "MyClass.method_a.inmethod.DeepInside.method_b", start=16, lines={17}),
78 CodeRegion(F, "MyClass.method_a.inmethod.DeepInside.Deeper.bb", start=19, lines={20}),
79 CodeRegion(F, "MyClass.InnerClass.method_c", start=25, lines={26}),
80 CodeRegion(F, "func", start=28, lines={29, 30, 31, 35, 36, 37, 39, 40}),
81 CodeRegion(F, "func.inner", start=31, lines={32, 33}),
82 CodeRegion(F, "func.inner.inner_inner", start=33, lines={34}),
83 CodeRegion(F, "func.InsideFunc.method_d", start=37, lines={38}),
84 CodeRegion(F, "afunc", start=42, lines={43}),
85 CodeRegion(C, "MyClass", start=5, lines={9, 12, 13, 14, 15, 16, 18, 19, 21}),
86 CodeRegion(C, "MyClass.method_a.inmethod.DeepInside", start=15, lines={17}),
87 CodeRegion(C, "MyClass.method_a.inmethod.DeepInside.Deeper", start=18, lines={20}),
88 CodeRegion(C, "MyClass.InnerClass", start=23, lines={26}),
89 CodeRegion(C, "func.InsideFunc", start=36, lines={38}),
90 ]
91 )
94def test_real_code_regions() -> None: 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
95 # Run code_regions on most of the coverage source code, checking that it
96 # succeeds and there are no overlaps.
98 any_fails = False 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
99 for source_file, source in all_our_source_files(): 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
100 regions = code_regions(source) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
101 for kind in ["function", "class"]: 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
102 kind_regions = [reg for reg in regions if reg.kind == kind] 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
103 line_counts = collections.Counter(lno for reg in kind_regions for lno in reg.lines) 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
104 overlaps = [line for line, count in line_counts.items() if count > 1] 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
105 if overlaps: # pragma: only failure 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
106 print(
107 f"{kind.title()} overlaps in {source_file.relative_to(Path.cwd())}: "
108 + f"{overlaps}"
109 )
110 any_fails = True
112 if any_fails: 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()
113 pytest.fail("Overlaps were found") # pragma: only failure