Loading util/junit_merge.py 0 → 100644 +92 −0 Original line number Diff line number Diff line # # Copyright 2018 Dominik Sekotill <dom.sekotill@kodo.org.uk> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Simple jUnit XML merger """ from xml.etree import ElementTree as etree # ElementTree is a stupid module name SUITE_METRICS = 'tests', 'failures', 'errors', 'skipped' def merge(testsuites, tree, name_format=None): """ Merge a jUnit tree into a 'testsuites' element """ assert testsuites.tag == 'testsuites' total_metrics = get_suite_metrics(testsuites) for test_suite in get_suites(tree): testsuites.append(test_suite) metrics = get_suite_metrics(test_suite) for name in metrics: total_metrics[name] += metrics[name] if name_format: test_suite.set('name', name_format.format(test_suite.get('name'))) for name, value in total_metrics.items(): testsuites.set(name, str(value)) def get_suite_metrics(suite): """ Return a dict of the metric attributes of a test suite """ metrics = {name: int(suite.get(name, 0)) for name in SUITE_METRICS} metrics['time'] = float(suite.get('time', 0.0)) if metrics['tests']: return metrics # No metric attributes: make some for testcase in suite.iter('testcase'): metrics['time'] += float(testcase.get('time', 0.0)) metrics['tests'] += 1 if testcase.find('failure'): metrics['failures'] += 1 elif testcase.find('error'): metrics['errors'] += 1 elif testcase.find('skipped'): metrics['skipped'] += 1 for name, value in metrics.items(): suite.set(name, str(value)) return metrics def get_suites(tree): root = tree.find('.') if root.tag == 'testsuite': return [root] return root.find('.//testsuite') if __name__ == '__main__': import sys testsuites = etree.Element('testsuites') testsuites.text = '\n' # .text & .tail are a deeply brain-dead design for arg in sys.argv[1:]: filename, *name_prefix = arg.split(':', 1) name_fmt = '{0[0]}: ({{}})'.format(name_prefix) if name_prefix else None tree = etree.parse(filename) merge(testsuites, tree, name_format=name_fmt) tree.getroot().tail = '\n' with open(1, 'wb') as stdout: ( etree.ElementTree(testsuites) .write(stdout, encoding='UTF-8', xml_declaration=True) ) Loading
util/junit_merge.py 0 → 100644 +92 −0 Original line number Diff line number Diff line # # Copyright 2018 Dominik Sekotill <dom.sekotill@kodo.org.uk> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Simple jUnit XML merger """ from xml.etree import ElementTree as etree # ElementTree is a stupid module name SUITE_METRICS = 'tests', 'failures', 'errors', 'skipped' def merge(testsuites, tree, name_format=None): """ Merge a jUnit tree into a 'testsuites' element """ assert testsuites.tag == 'testsuites' total_metrics = get_suite_metrics(testsuites) for test_suite in get_suites(tree): testsuites.append(test_suite) metrics = get_suite_metrics(test_suite) for name in metrics: total_metrics[name] += metrics[name] if name_format: test_suite.set('name', name_format.format(test_suite.get('name'))) for name, value in total_metrics.items(): testsuites.set(name, str(value)) def get_suite_metrics(suite): """ Return a dict of the metric attributes of a test suite """ metrics = {name: int(suite.get(name, 0)) for name in SUITE_METRICS} metrics['time'] = float(suite.get('time', 0.0)) if metrics['tests']: return metrics # No metric attributes: make some for testcase in suite.iter('testcase'): metrics['time'] += float(testcase.get('time', 0.0)) metrics['tests'] += 1 if testcase.find('failure'): metrics['failures'] += 1 elif testcase.find('error'): metrics['errors'] += 1 elif testcase.find('skipped'): metrics['skipped'] += 1 for name, value in metrics.items(): suite.set(name, str(value)) return metrics def get_suites(tree): root = tree.find('.') if root.tag == 'testsuite': return [root] return root.find('.//testsuite') if __name__ == '__main__': import sys testsuites = etree.Element('testsuites') testsuites.text = '\n' # .text & .tail are a deeply brain-dead design for arg in sys.argv[1:]: filename, *name_prefix = arg.split(':', 1) name_fmt = '{0[0]}: ({{}})'.format(name_prefix) if name_prefix else None tree = etree.parse(filename) merge(testsuites, tree, name_format=name_fmt) tree.getroot().tail = '\n' with open(1, 'wb') as stdout: ( etree.ElementTree(testsuites) .write(stdout, encoding='UTF-8', xml_declaration=True) )