Source code for nose2unitth.core

""" Convert nose-style test reports to UnitTH-style test reports by splitting modules into separate XML files

:Author: Jonathan Karr <karr@mssm.edu>
:Date: 2017-07-27
:Copyright: 2016, Karr Lab
:License: MIT
"""

from __future__ import unicode_literals
from xml.dom import minidom
import os


[docs]class Converter(object): """ Convert nose-style test reports to UnitTH-style test reports by splitting modules into separate XML files """ @staticmethod
[docs] def run(in_file_nose, out_dir_unitth): """ Convert nose-style test reports to UnitTH-style test reports by splitting modules into separate XML files Args: in_file_nose (:obj:`str`): path to nose-style test report out_file_unitth (:obj:`str`): path to save UnitTH-style test reports """ suites = Converter.read_nose(in_file_nose) Converter.write_unitth(suites, out_dir_unitth)
@staticmethod
[docs] def read_nose(in_file): """ Parse nose-style test reports into a `dict` Args: in_file (:obj:`str`): path to nose-style test report Returns: :obj:`dict`: dictionary of test suites """ suites = {} doc_xml = minidom.parse(in_file) suite_xml = doc_xml.getElementsByTagName("testsuite")[0] for case_xml in suite_xml.getElementsByTagName('testcase'): classname = case_xml.getAttribute('classname') if classname not in suites: suites[classname] = [] case = { 'name': case_xml.getAttribute('name'), 'time': float(case_xml.getAttribute('time')), } skipped_xml = case_xml.getElementsByTagName('skipped') if skipped_xml: if skipped_xml[0].hasAttribute('type'): type = skipped_xml[0].getAttribute('type') else: type = '' case['skipped'] = { 'type': type, 'message': skipped_xml[0].getAttribute('message'), 'text': "".join([child.nodeValue for child in skipped_xml[0].childNodes]), } failure_xml = case_xml.getElementsByTagName('failure') if failure_xml: if failure_xml[0].hasAttribute('type'): type = failure_xml[0].getAttribute('type') else: type = '' case['failure'] = { 'type': type, 'message': failure_xml[0].getAttribute('message'), 'text': "".join([child.nodeValue for child in failure_xml[0].childNodes]), } error_xml = case_xml.getElementsByTagName('error') if error_xml: if error_xml[0].hasAttribute('type'): type = error_xml[0].getAttribute('type') else: type = '' case['error'] = { 'type': type, 'message': error_xml[0].getAttribute('message'), 'text': "".join([child.nodeValue for child in error_xml[0].childNodes]), } suites[classname].append(case) return suites
@staticmethod
[docs] def write_unitth(suites, out_dir): """ Write UnitTH-style test reports Args: suites (:obj:`dict`): dictionary of test suites out_dir (:obj:`str`): path to save UnitTH-style test reports """ if not os.path.isdir(out_dir): os.mkdir(out_dir) for classname, cases in suites.items(): doc_xml = minidom.Document() suite_xml = doc_xml.createElement('testsuite') suite_xml.setAttribute('name', classname) suite_xml.setAttribute('tests', str(len(cases))) suite_xml.setAttribute('errors', str(sum('error' in case for case in cases))) suite_xml.setAttribute('failures', str(sum('failure' in case for case in cases))) suite_xml.setAttribute('skipped', str(sum('skipped' in case for case in cases))) suite_xml.setAttribute('time', '{:.3f}'.format(sum(case['time'] for case in cases))) doc_xml.appendChild(suite_xml) for case in cases: case_xml = doc_xml.createElement('testcase') case_xml.setAttribute('classname', classname) case_xml.setAttribute('name', case['name']) case_xml.setAttribute('time', '{:.3f}'.format(case['time'])) suite_xml.appendChild(case_xml) if 'skipped' in case: skipped_xml = doc_xml.createElement('skipped') skipped_xml.setAttribute('type', case['skipped']['type']) skipped_xml.setAttribute('message', case['skipped']['message']) case_xml.appendChild(skipped_xml) skipped_text_xml = doc_xml.createCDATASection(case['skipped']['text']) skipped_xml.appendChild(skipped_text_xml) if 'failure' in case: failure_xml = doc_xml.createElement('failure') failure_xml.setAttribute('type', case['failure']['type']) failure_xml.setAttribute('message', case['failure']['message']) case_xml.appendChild(failure_xml) failure_text_xml = doc_xml.createCDATASection(case['failure']['text']) failure_xml.appendChild(failure_text_xml) if 'error' in case: error_xml = doc_xml.createElement('error') error_xml.setAttribute('type', case['error']['type']) error_xml.setAttribute('message', case['error']['message']) case_xml.appendChild(error_xml) error_text_xml = doc_xml.createCDATASection(case['error']['text']) error_xml.appendChild(error_text_xml) with open(os.path.join(out_dir, '{}.xml'.format(classname)), 'w') as output: doc_xml.writexml(output, encoding='utf-8', addindent='', newl="") doc_xml.unlink()