-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathget_methed_coverage.py
More file actions
97 lines (78 loc) · 3.63 KB
/
get_methed_coverage.py
File metadata and controls
97 lines (78 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import argparse
import os
import sys
import xml.etree.ElementTree as ET
def print_counter(counter_element, counter_type):
"""Helper to format and print coverage data with color."""
missed = int(counter_element.get('missed', 0))
covered = int(counter_element.get('covered', 0))
total = missed + covered
if total > 0:
ratio = (covered / total) * 100
# ANSI colors: Green (100%), Yellow (>0%), Red (0%)
color = "\033[92m" if ratio == 100 else ("\033[93m" if ratio > 0 else "\033[91m")
reset = "\033[0m"
print(f" - {counter_type:<12}: {color}{ratio:6.2f}%{reset} (Covered: {covered} / Total: {total})")
else:
print(f" - {counter_type:<12}: N/A (Empty block)")
def analyze_coverage(xml_path, target_method, target_class=None):
"""
Parses JaCoCo XML.
- Always filters by 'target_method'.
- Optionally filters by 'target_class' if provided.
"""
if not os.path.exists(xml_path):
print(f"Error: File not found at {xml_path}")
sys.exit(1)
try:
tree = ET.parse(xml_path)
root = tree.getroot()
except ET.ParseError:
print(f"Error: Could not parse XML. Check if {xml_path} is valid.")
sys.exit(1)
matches_found = 0
# User feedback
if target_class:
print(f"\nSearching for method '{target_method}' in class containing '{target_class}'...")
else:
print(f"\nSearching for method '{target_method}' in ALL classes...")
# Iterate through packages
for package in root.findall('package'):
# Iterate through classes
for clazz in package.findall('class'):
class_name = clazz.get('name') # e.g., com/example/MyService
# --- FILTER: Class Name (Optional) ---
# If target_class is provided, skip if it's not part of the current class_name
if target_class and (target_class not in class_name):
continue
# Iterate through methods
for method in clazz.findall('method'):
if method.get('name') == target_method:
matches_found += 1
print(f"[{matches_found}] Class: \033[1m{class_name}\033[0m | Method: \033[1m{target_method}\033[0m")
# Map counters
counters = {c.get('type'): c for c in method.findall('counter')}
# Print in preferred order
order = ['INSTRUCTION', 'BRANCH', 'LINE', 'COMPLEXITY']
for c_type in order:
if c_type in counters:
print_counter(counters[c_type], c_type)
print("-" * 60)
if matches_found == 0:
if target_class:
print(f"No matches found for method '{target_method}' in class '{target_class}'.")
else:
print(f"No method named '{target_method}' found in the report.")
else:
print(f"\nTotal matches found: {matches_found}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Extract coverage stats for a specific method from JaCoCo XML.")
# 1. XML Path (Required)
parser.add_argument("xml_path", help="Path to the jacoco.xml file")
# 2. Method Name (Required)
parser.add_argument("method_name", help="The function/method name to search for")
# 3. Class Name (Optional) - using nargs='?' makes it optional
parser.add_argument("class_name", nargs="?", default=None,
help="Optional: Partial class name to filter results (e.g. 'UserService')")
args = parser.parse_args()
analyze_coverage(args.xml_path, args.method_name, args.class_name)