ChibiOS/tools/workflows/report.py

143 lines
3.9 KiB
Python
Executable File

#!/usr/bin/env python
"""Scan test results directory and report status."""
import argparse
import os
import sys
from xml.etree import ElementTree
def report(args, fd):
def write_brief_status(fd, testcase, status):
fd.write('{makefile} ({target}) ... {status} {message}\n'.format(
makefile=testcase.attrib['file'],
target=testcase.attrib['name'],
status=status.attrib['type'],
message=status.attrib['message']
))
def write_brief_ok(fd, testcase):
fd.write('{makefile} ({target}) ... ok\n'.format(
makefile=testcase.attrib['file'],
target=testcase.attrib['name'],
))
def write_failed_status(fd, testcase):
fd.write(thick_line)
fd.write('FAIL: {makefile} ({target})\n'.format(
makefile=testcase.attrib['file'],
target=testcase.attrib['name'],
))
fd.write(thin_line)
fd.write('CMD: {}\n'.format(testcase.attrib['log']))
stdout = testcase.find('system-out')
if stdout is not None:
fd.write('\nSTDOUT:\n')
fd.write(stdout.text)
stderr = testcase.find('system-err')
if stderr is not None:
fd.write('\nSTDERR:\n')
fd.write(stderr.text)
fd.write('\n')
def write(fds, string):
for fd in fds:
fd.write(string)
thick_line = '=' * 70 + '\n'
thin_line = '-' * 70 + '\n'
time = 0
total_count = 0
skipped_count = 0
failures = []
for root_dir, _, files in os.walk(args.test_results):
for file in files:
if file.endswith('.xml'):
path = os.path.join(root_dir, file)
tree = ElementTree.parse(path)
for testcase in tree.iter('testcase'):
time += float(testcase.attrib['time'])
total_count += 1
fail = testcase.find('failure')
if fail is not None:
if args.verbose == 1:
write_brief_status(fd, testcase, fail)
failures.append(testcase)
continue
skip = testcase.find('skipped')
if skip is not None:
if args.verbose == 1:
write_brief_status(fd, testcase, skip)
skipped_count += 1
continue
if args.verbose == 1:
write_brief_ok(fd, testcase)
failures_count = len(failures)
if args.verbose == 1 and (failures_count > 0 or skipped_count > 0):
fd.write('\n')
for testcase in failures:
write_failed_status(fd, testcase)
fds = [fd]
if fd != sys.stdout:
fds.append(sys.stdout)
write(fds, thin_line)
write(fds, 'Ran {total:d} tests in {time:.3f}s\n\n'.format(
total=total_count,
time=time,
))
context = ', '.join(
'{}={}'.format(*v)
for v in [
('failures', failures_count),
('skipped', skipped_count),
]
if v[1] > 0
)
if failures_count > 0:
write(fds, 'FAILED ({})\n'.format(context))
sys.exit(1)
if context:
write(fds, 'OK ({})\n'.format(context))
sys.exit(0)
write(fds, 'OK\n')
def main():
parser = argparse.ArgumentParser(description=(
'Scan test results and report status'
))
parser.add_argument('-v', '--verbose', action='count', default=0)
parser.add_argument('-t', '--test-results',
help='Directory with JUnit XML test results')
parser.add_argument('-r', '--report', default='-',
help='Filename to store test report')
args = parser.parse_args()
if args.report == '-':
report(args, sys.stdout)
else:
with open(args.report, 'w') as fd:
report(args, fd)
if __name__ == '__main__':
main()