Fork for workshops

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers unity_to_junit.py Source File

unity_to_junit.py

00001 import sys
00002 import os
00003 from glob import glob
00004 
00005 from pyparsing import *
00006 from junit_xml import TestSuite, TestCase
00007 
00008 
00009 class UnityTestSummary:
00010     def __init__(self):
00011         self.report = ''
00012         self.total_tests = 0
00013         self.failures = 0
00014         self.ignored = 0
00015         self.targets = 0
00016         self.root = None
00017         self.test_suites = dict()
00018 
00019     def run(self):
00020         # Clean up result file names
00021         results = []
00022         for target in self.targets:
00023             results.append(target.replace('\\', '/'))
00024 
00025         # Dig through each result file, looking for details on pass/fail:
00026         for result_file in results:
00027             lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
00028             if len(lines) == 0:
00029                 raise Exception("Empty test result file: %s" % result_file)
00030 
00031             # define an expression for your file reference
00032             entry_one = Combine(
00033                 oneOf(list(alphas)) + ':/' +
00034                 Word(alphanums + '_-./'))
00035 
00036             entry_two = Word(printables + ' ', excludeChars=':')
00037             entry = entry_one | entry_two
00038 
00039             delimiter = Literal(':').suppress()
00040             tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName(
00041                 'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName(
00042                 'tc_status') + Optional(
00043                 delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
00044 
00045             eol = LineEnd().suppress()
00046             sol = LineStart().suppress()
00047             blank_line = sol + eol
00048 
00049             tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
00050                 "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
00051                 "tc_summary")
00052             tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result")
00053 
00054             # run it and see...
00055             pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line)
00056             pp1.ignore(blank_line | OneOrMore("-"))
00057 
00058             result = list()
00059             for l in lines:
00060                 result.append((pp1.parseString(l)).asDict())
00061             # delete empty results
00062             result = filter(None, result)
00063 
00064             tc_list = list()
00065             for r in result:
00066                 if 'tc_line' in r:
00067                     tmp_tc_line = r['tc_line']
00068 
00069                     # get only the file name which will be used as the classname
00070                     file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
00071                     tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
00072                     if 'tc_status' in tmp_tc_line:
00073                         if str(tmp_tc_line['tc_status']) == 'IGNORE':
00074                             if 'tc_msg' in tmp_tc_line:
00075                                 tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'],
00076                                                         output=r'[File]={0}, [Line]={1}'.format(
00077                                                             tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
00078                             else:
00079                                 tmp_tc.add_skipped_info(message=" ")
00080                         elif str(tmp_tc_line['tc_status']) == 'FAIL':
00081                             if 'tc_msg' in tmp_tc_line:
00082                                 tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'],
00083                                                         output=r'[File]={0}, [Line]={1}'.format(
00084                                                             tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
00085                             else:
00086                                 tmp_tc.add_failure_info(message=" ")
00087 
00088                     tc_list.append((str(result_file), tmp_tc))
00089 
00090             for k, v in tc_list:
00091                 try:
00092                     self.test_suites[k].append(v)
00093                 except KeyError:
00094                     self.test_suites[k] = [v]
00095         ts = []
00096         for suite_name in self.test_suites:
00097             ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
00098 
00099         with open('result.xml', 'w') as f:
00100             TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
00101 
00102         return self.report
00103 
00104     def set_targets(self, target_array):
00105         self.targets = target_array
00106 
00107     def set_root_path(self, path):
00108         self.root = path
00109 
00110     @staticmethod
00111     def usage(err_msg=None):
00112         print("\nERROR: ")
00113         if err_msg:
00114             print(err_msg)
00115         print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
00116         print("     result_file_directory - The location of your results files.")
00117         print("                             Defaults to current directory if not specified.")
00118         print("                             Should end in / if specified.")
00119         print("     root_path - Helpful for producing more verbose output if using relative paths.")
00120         sys.exit(1)
00121 
00122 
00123 if __name__ == '__main__':
00124     uts = UnityTestSummary()
00125     try:
00126         # look in the specified or current directory for result files
00127         if len(sys.argv) > 1:
00128             targets_dir = sys.argv[1]
00129         else:
00130             targets_dir = './'
00131         targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
00132         if len(targets) == 0:
00133             raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
00134         uts.set_targets(targets)
00135 
00136         # set the root path
00137         if len(sys.argv) > 2:
00138             root_path = sys.argv[2]
00139         else:
00140             root_path = os.path.split(__file__)[0]
00141         uts.set_root_path(root_path)
00142 
00143         # run the summarizer
00144         print(uts.run())
00145     except Exception as e:
00146         UnityTestSummary.usage(e)