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

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 

3 

4"""Tests for coverage/regions.py.""" 

5 

6from __future__ import annotations 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

7 

8import collections 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

9import textwrap 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

10from pathlib import Path 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

11 

12import pytest 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

13 

14from coverage.plugin import CodeRegion 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

15from coverage.regions import code_regions 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

16 

17from tests.helpers import all_our_source_files 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

18 

19 

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''' 

25 

26 CONST = 4 

27 class MyClass: 

28 class_attr = 6 

29 

30 def __init__(self): 

31 self.x = 9 

32 

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 

44 

45 class InnerClass: 

46 constant = 24 

47 def method_c(self): 

48 self.x = 26 

49 

50 def func(): 

51 x = 29 

52 y = 30 

53 def inner(): 

54 z = 32 

55 def inner_inner(): 

56 w = 34 

57 

58 class InsideFunc: 

59 def method_d(self): 

60 self.x = 38 

61 

62 return 40 

63 

64 async def afunc(): 

65 x = 43 

66 """) 

67 ) 

68 

69 F = "function" 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

70 C = "class" 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

71 

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 ) 

92 

93 

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. 

97 

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 

111 

112 if any_fails: 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()

113 pytest.fail("Overlaps were found") # pragma: only failure