From 4f25c87f896ed426ea75528a69547b2dc8ae2d42 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 9 Jan 2019 17:01:27 +0900 Subject: [PATCH] JenkinsHelper --- NUnit3To2FormatConverter.py | 230 ++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 NUnit3To2FormatConverter.py diff --git a/NUnit3To2FormatConverter.py b/NUnit3To2FormatConverter.py new file mode 100644 index 000000000..82bd3a619 --- /dev/null +++ b/NUnit3To2FormatConverter.py @@ -0,0 +1,230 @@ +#! /usr/bin/env python +# https://answers.unity.com/questions/1355795/can-unity-56s-test-runner-optionally-output-nunit.html + +import argparse +import os +import sys +import xml.dom.minidom + + +def convert(input_path, output_path): + ''' Converts the input file from the NUnit 3 format to NUnit 2 format + and writes the result into output_path. + ''' + + def read_input(input_path): + dom_tree = xml.dom.minidom.parse(input_path) + collection = dom_tree.documentElement + + tests = collection.getElementsByTagName('test-case') + + results = {} + results['name'] = collection.getAttribute('name') + results['time'] = collection.getAttribute('duration') + + test_results = [] + results['test_results'] = test_results + + num_tests = 0 + num_passed_tests = 0 + num_failed_tests = 0 + num_ignored_tests = 0 + num_skipped_tests = 0 + + for test in tests: + num_tests = num_tests + 1 + curr_test_results = {} + curr_test_results['name'] = test.getAttribute('fullname') + test_new_result = test.getAttribute('result') + test_new_runstate = test.getAttribute('runstate') + + if (test_new_result == 'Passed'): + # Test Passed... + num_passed_tests = num_passed_tests + 1 + curr_test_results['state'] = 'Success' + curr_test_results['result'] = 'Success' + curr_test_results['executed'] = 'True' + curr_test_results['state'] = 'Success' + curr_test_results['success'] = 'True' + curr_test_results['time'] = test.getAttribute('duration') + elif (test_new_result == 'Failed'): + if (test_new_runstate == 'Runnable'): + # Test Failed... + num_failed_tests = num_failed_tests + 1 + curr_test_results['state'] = 'Failed' + curr_test_results['result'] = 'Failure' + curr_test_results['executed'] = 'True' + curr_test_results['success'] = 'False' + curr_test_results['time'] = test.getAttribute('duration') + + failure_elem = test.getElementsByTagName('failure')[0] + + curr_test_results['failure_message'] = failure_elem.getElementsByTagName('message')[0].firstChild.wholeText + curr_test_results['failure_stacktrace'] = failure_elem.getElementsByTagName('stack-trace')[0].firstChild.wholeText + else: + # Test could not be run... + num_skipped_tests = num_skipped_tests + 1 + assert(test_new_runstate == 'NotRunnable') + curr_test_results['state'] = 'NotRunnable' + curr_test_results['result'] = 'NotRunnable' + curr_test_results['executed'] = 'False' + curr_test_results['success'] = 'False' + curr_test_results['time'] = test.getAttribute('duration') + + curr_test_results['reason_message'] = test.getElementsByTagName('failure')[0].getElementsByTagName('message')[0].firstChild.wholeText + elif (test_new_result == 'Skipped'): + # Test was Ignored... + num_ignored_tests = num_ignored_tests + 1 + curr_test_results['state'] = 'Ignored' + curr_test_results['result'] = 'Ignored' + curr_test_results['executed'] = 'False' + curr_test_results['reason_message'] = test.getElementsByTagName('reason')[0].getElementsByTagName('message')[0].firstChild.wholeText + else: + assert(False) #Unknown test result type? + test_results.append(curr_test_results) + + results['num_tests'] = num_tests + results['num_passed_tests'] = num_passed_tests + results['num_failed_tests'] = num_failed_tests + results['num_ignored_tests'] = num_ignored_tests + results['num_skipped_tests'] = num_skipped_tests + + date_time = collection.getAttribute('start-time').split(' ') + results['date'] = date_time[0] + results['time'] = date_time[1] + + return results + + def write_output(results, output_path): + # Write XML File (minidom) + + doc = xml.dom.minidom.Document() + + num_tests = results['num_tests'] + num_skipped_tests = results['num_skipped_tests'] + num_ignored_tests = results['num_ignored_tests'] + num_not_run_tests = num_skipped_tests + num_ignored_tests + num_failed_tests = results['num_failed_tests'] + + suite_executed = (num_tests - num_not_run_tests) > 0 + suite_success = num_skipped_tests + num_failed_tests == 0 + + root = doc.createElement('test-results') + root.setAttribute('name', 'Unity Tests') + root.setAttribute('total', str(num_tests - num_not_run_tests)) + root.setAttribute('errors', str(0)) + root.setAttribute('failures', str(num_failed_tests)) + root.setAttribute('not-run', str(num_not_run_tests)) + root.setAttribute('inconclusive', str(0)) + root.setAttribute('ignored', str(num_ignored_tests)) + root.setAttribute('skipped', str(num_skipped_tests)) + root.setAttribute('invalid', str(0)) + root.setAttribute('date', str(results['date'])) + root.setAttribute('time', str(results['time'])) + doc.appendChild(root) + + test_suite = doc.createElement('test-suite') + test_suite.setAttribute('name', results['name']) + test_suite.setAttribute('type', 'Assembly') + test_suite.setAttribute('executed', 'True' if suite_executed else 'False') + test_suite.setAttribute('result', 'Success' if suite_success else 'Failure') + test_suite.setAttribute('success', 'True' if suite_success else 'False') + test_suite.setAttribute('time', results['time']) + root.appendChild(test_suite) + + results_elem = doc.createElement('results') + test_suite.appendChild(results_elem) + + + test_results = results['test_results'] + for curr_test_results in test_results: + + test_case = doc.createElement('test-case') + results_elem.appendChild(test_case) + + test_case.setAttribute('name', curr_test_results['name']) + test_case.setAttribute('executed', curr_test_results['executed']) + test_case.setAttribute('result', curr_test_results['result']) + + run_state = curr_test_results['state'] + if (run_state == 'Success'): + # Success... + test_case.setAttribute('success', curr_test_results['success']) + test_case.setAttribute('time', curr_test_results['time']) + + elif (run_state == 'Failed'): + # Failed... + test_case.setAttribute('success', curr_test_results['success']) + test_case.setAttribute('time', curr_test_results['time']) + + failure = doc.createElement('failure') + test_case.appendChild(failure) + + message = doc.createElement('message') + message_cdata = doc.createCDATASection(curr_test_results['failure_message']) + message.appendChild(message_cdata) + failure.appendChild(message) + + stack_trace = doc.createElement('stack-trace') + stack_trace_cdata = doc.createCDATASection(curr_test_results['failure_stacktrace']) + stack_trace.appendChild(stack_trace_cdata) + failure.appendChild(stack_trace) + + elif (run_state == 'NotRunnable'): + # Not Runnable... + test_case.setAttribute('success', curr_test_results['success']) + test_case.setAttribute('time', curr_test_results['time']) + + reason = doc.createElement('reason') + test_case.appendChild(reason) + + message = doc.createElement('message') + message_cdata = doc.createCDATASection(curr_test_results['reason_message']) + message.appendChild(message_cdata) + reason.appendChild(message) + + elif(run_state == 'Ignored'): + + reason = doc.createElement('reason') + test_case.appendChild(reason) + + message = doc.createElement('message') + message_cdata = doc.createCDATASection(curr_test_results['reason_message']) + message.appendChild(message_cdata) + reason.appendChild(message) + + else: + print ("Unknown run state: " + run_state) + + doc.writexml( open(output_path, 'w'), + indent=" ", + addindent=" ", + newl='\n') + + doc.unlink() + + results = read_input(input_path) + write_output(results, output_path) + + +def main(): + parser = argparse.ArgumentParser(description='Convert an NUnit 3 file to an NUnit 2 file') + required_named = parser.add_argument_group('Required named arguments') + required_named.add_argument('-i', '--input', dest='input', help='Input file name', required=True) + required_named.add_argument('-o', '--output', dest='output', help='Output file name', required=True) + args = parser.parse_args() + + input_path = args.input + output_path = args.output + + if (not os.path.isfile(input_path)): + print ("Input file does not exist") + return 1 + + print ("Converting " + input_path + " to " + output_path) + convert(input_path, output_path) + return 0 + + +if __name__ == "__main__": + sys.exit(main())