| # Copyright 2019 NXP | |
| # | |
| # SPDX-License-Identifier: Apache-2.0 | |
| # | |
| import datetime | |
| import os | |
| import csv | |
| import sys | |
| import xml.etree.cElementTree as et | |
| import xml.dom.minidom as dom | |
| __VERSION__ = "2018.12.18_00" | |
| # | |
| # Changelog: | |
| # | |
| # 2018.12.18_00 : PGh : Capture timestamps | |
| # : : | |
| # 2018.12.14_00 : PGh : Added root suite name | |
| # : : | |
| # 2018.08.02_00 : PGh : Add failure message as well | |
| # : : | |
| # 2018.08.01_01 : PGh : Code Cleanup | |
| # : : | |
| # 2018.08.01_00 : CAy : Initial implementaiton | |
| # | |
| # | |
| # Todo: | |
| # - Handle case of appended results. | |
| # - Handle case of Ignore | |
| # - Handle case of Suites | |
| # | |
| DEBUG = True | |
| def csv_to_unit_xml(root_name, in_csv, out_xml): | |
| csv_data = list() | |
| with open(in_csv) as csvfile: | |
| read_file = csv.reader(csvfile, delimiter = ',') | |
| for row in read_file: | |
| csv_data.append(row) | |
| if len(csv_data) == 0 or len(csv_data[0]) == 1: | |
| print("ERROR: Empty %s"%(in_csv)) | |
| return | |
| fail_count=0 | |
| for i in csv_data: | |
| if (i[5]=="FAILED"): | |
| fail_count=fail_count+1 | |
| suite_name = csv_data[0][2] | |
| suite_start = int(csv_data[0][6]) | |
| suite_end = int(csv_data[-1][7]) | |
| if (suite_start == 0): | |
| timestamp = datetime.datetime.now().isoformat() | |
| else: | |
| timestamp = datetime.datetime.utcfromtimestamp(suite_start).isoformat() | |
| if root_name: | |
| testsuites = et.Element("testsuites", | |
| name="%s"%root_name, | |
| #id="0", | |
| tests="%d"%(len(csv_data)), | |
| errors="0", | |
| failures="%d"%fail_count, | |
| time="%ssec"%(1 + suite_end - suite_start), | |
| timstamp=timestamp) | |
| suite_name="%s.%s"%(root_name, suite_name) | |
| subsuites = et.SubElement(testsuites, | |
| "testsuite", | |
| name=suite_name, | |
| #id="0", | |
| tests="%d"%(len(csv_data)), | |
| errors="0", | |
| failures="%d"%fail_count, | |
| time="%ssec"%(1 + suite_end - suite_start), | |
| timstamp=timestamp ) | |
| else: | |
| testsuites = et.Element("testsuites", | |
| name=suite_name, | |
| #id="0", | |
| tests="%d"%(len(csv_data)), | |
| errors="0", | |
| failures="%d"%fail_count, | |
| time="%ssec"%(1 + suite_end - suite_start), | |
| timstamp=timestamp) | |
| subsuites = testsuites | |
| all_ts = {} | |
| all_times = {} | |
| for i in csv_data: | |
| (file_name, line_number, test_suite, test_name, _, test_status, test_start, test_end, test_message) = i | |
| test_time = int(test_end) - int(test_start) | |
| if root_name: | |
| suite_name="%s.%s"%(root_name, test_suite) | |
| else: | |
| suite_name=test_suite | |
| if suite_name in all_times: | |
| all_times[suite_name] += test_time | |
| else: | |
| all_times[suite_name] = test_time | |
| if suite_name in all_ts: | |
| ts = all_ts[suite_name] | |
| else: | |
| ts = et.SubElement(subsuites, | |
| "testsuite", | |
| name=suite_name, | |
| #id="0", | |
| tests="%d"%(len(csv_data)), | |
| errors="0", | |
| failures="%d"%fail_count, | |
| time="%ssec"%(1 + int(test_end) - int(test_start)), | |
| timstamp=datetime.datetime.utcfromtimestamp(int(test_start)).isoformat()) | |
| all_ts[suite_name] = ts | |
| tc = et.SubElement(ts, | |
| "testcase", | |
| classname=suite_name, | |
| name="%s"%test_name, | |
| status="%s"%test_status, | |
| time="%ssec"%(1 + int(test_end) - int(test_start)), | |
| timstamp=datetime.datetime.utcfromtimestamp(int(test_start)).isoformat()) | |
| if (test_status=="FAILED"): | |
| et.SubElement(tc,"failure",message="%s"%file_name, type="FAILURE").text="Error %s in file %s in line %s"%(test_message, file_name,line_number) | |
| for k,v in all_times.items(): | |
| all_ts[k].set("time","%ssec"%(1 + v,)) | |
| tree = et.ElementTree(testsuites) | |
| tree.write(out_xml) | |
| if DEBUG: | |
| xml = dom.parse(out_xml) | |
| formatted_xml = xml.toprettyxml() | |
| f = open(out_xml,"w+") | |
| f.write("%s"%formatted_xml) | |
| f.close() | |
| def usage(prog_name): | |
| print("%s [in:root_name] <in:csv> <out:junit_xml>"%(prog_name,)) | |
| def main(): | |
| if len(sys.argv) == 3: | |
| csv_to_unit_xml(None, sys.argv[1],sys.argv[2]) | |
| elif len(sys.argv) == 4: | |
| csv_to_unit_xml(sys.argv[1], sys.argv[2], sys.argv[3]) | |
| else: | |
| if DEBUG: | |
| test(r'C:\temp\unity_in.csv', r'C:\temp\junit_out.xml') | |
| else: | |
| usage(sys.argv[0]) | |
| if __name__ == '__main__': | |
| main() |