Skip to content

Commit 0e5dc30

Browse files
authored
Merge pull request #254 from wazuh/change/26466-pytest-ut-coverage-workflow
Add script for pytest coverage test
2 parents 0e0c3c5 + 57f4516 commit 0e5dc30

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

Diff for: requirements.txt

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
chardet==3.0.4
2+
coverage==7.3.2
23
filetype>=1.0.7
3-
jsonschema==3.2.0
4+
jsonschema==4.17.3
45
psutil>=5.6.6
56
py~=1.11.0
67
pycryptodome>=3.18.0
78
pyOpenSSL>=19.1.0
89
pytest-html==3.1.1
910
pytest==6.2.2 ; python_version <= "3.9"
10-
pytest==7.1.2 ; python_version >= "3.10"
11+
pytest==7.3.1 ; python_version >= "3.10"
12+
pytest-cov==4.1.0
1113
pyyaml>=6.0.1
1214
requests>=2.23.0
1315
pywin32>=305; sys_platform == "win32"

Diff for: src/wazuh_testing/scripts/pytest_coverage.py

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import argparse
2+
import re
3+
import subprocess
4+
from os import chdir, remove
5+
from os.path import basename, exists, join, dirname
6+
7+
PYTHON_MODULES = (
8+
'framework', # Framework
9+
'api/api', # API
10+
'wodles', # External modules
11+
'integrations' # Integrations
12+
)
13+
14+
COVERAGE_FILE = '.coverage'
15+
COVERAGE_REPORT = ''
16+
COVERAGE_REGEX = r'^([\w\/._-]+) +(\d+) +(\d+) +(\d+)\%$'
17+
GLOBAL_STMTS = 0
18+
GLOBAL_MISS = 0
19+
TABLE_HEADER = """| | | | | |
20+
|--|--|--|--|--|
21+
| **Name** | **Stmts** | **Miss** | **Cover** | **Status** |
22+
"""
23+
24+
25+
def obtain_coverage(module):
26+
chdir(dirname(module))
27+
module_basename = basename(module)
28+
29+
module_report = f'### {module_basename.upper()}\n\n{TABLE_HEADER}'
30+
subprocess.run(['coverage', 'run', '--omit=*test*', '--source', module_basename,
31+
'-m', 'pytest', module_basename],
32+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
33+
34+
coverage_result = subprocess.check_output(['coverage', 'report']).decode().strip()
35+
test_coverage_results = re.findall(COVERAGE_REGEX, coverage_result, re.MULTILINE)
36+
for test in test_coverage_results:
37+
# test_name stmts miss cover
38+
coverage = int(test[3])
39+
if coverage >= 75:
40+
check = ':green_square:'
41+
elif coverage >= 50:
42+
check = ':yellow_square:'
43+
elif coverage >= 25:
44+
check = ':orange_square:'
45+
else:
46+
check = ':red_square:'
47+
48+
module_report = f'{module_report}| {test[0]} | {test[1]} | {test[2]} | {coverage}% | {check} |\n'
49+
50+
global COVERAGE_REPORT
51+
COVERAGE_REPORT = f'{COVERAGE_REPORT}{module_report}\n'
52+
53+
global GLOBAL_STMTS, GLOBAL_MISS
54+
GLOBAL_STMTS += int(test_coverage_results[-1][1])
55+
GLOBAL_MISS += int(test_coverage_results[-1][2])
56+
57+
# Remove .coverage file
58+
exists(COVERAGE_FILE) and remove(COVERAGE_FILE)
59+
60+
61+
def parse_arguments():
62+
parser = argparse.ArgumentParser(description='Pytest Coverage (Wazuh)')
63+
parser.add_argument('-p', '--path', dest='wazuh_path', action='store', required=True,
64+
help='Path to the Wazuh repository.')
65+
66+
return parser.parse_args()
67+
68+
69+
def main():
70+
arguments = parse_arguments()
71+
wazuh_path = arguments.wazuh_path
72+
73+
if not exists(wazuh_path):
74+
print(f'Base Wazuh path is not valid: {wazuh_path}')
75+
exit(1)
76+
77+
for module in PYTHON_MODULES:
78+
current_module_path = join(wazuh_path, module)
79+
80+
if not exists(current_module_path):
81+
print(f'Wazuh module path is not valid: {current_module_path}')
82+
exit(1)
83+
84+
obtain_coverage(current_module_path)
85+
86+
print(COVERAGE_REPORT)
87+
print(f'\nOVERALL COVERAGE PERCENTAGE: {100 - int(GLOBAL_MISS * 100 / GLOBAL_STMTS)}%')
88+
89+
90+
if __name__ == '__main__':
91+
main()

0 commit comments

Comments
 (0)