143 lines
3.9 KiB
Python
Executable File
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()
|