1#!/usr/bin/env python3 2 3from enum import Enum 4 5class ResultState(Enum): 6 noresult = -1 7 skip = 0 8 success = 1 9 fail = 2 10 11class TestResult: 12 def __init__(self, test_id="", test_name=""): 13 self.test_id = test_id 14 self.test_name = test_name 15 self.result = ResultState.noresult 16 self.failmsg = "" 17 self.errormsg = "" 18 self.steps = [] 19 20 def set_result(self, result): 21 if (isinstance(result, ResultState)): 22 self.result = result 23 return True 24 else: 25 raise TypeError('Unknown result type, must be type ResultState') 26 27 def get_result(self): 28 return self.result 29 30 def set_errormsg(self, errormsg): 31 self.errormsg = errormsg 32 return True 33 34 def append_errormsg(self, errormsg): 35 self.errormsg = '{}\n{}'.format(self.errormsg, errormsg) 36 37 def get_errormsg(self): 38 return self.errormsg 39 40 def set_failmsg(self, failmsg): 41 self.failmsg = failmsg 42 return True 43 44 def append_failmsg(self, failmsg): 45 self.failmsg = '{}\n{}'.format(self.failmsg, failmsg) 46 47 def get_failmsg(self): 48 return self.failmsg 49 50 def add_steps(self, newstep): 51 if type(newstep) == list: 52 self.steps.extend(newstep) 53 elif type(newstep) == str: 54 self.steps.append(step) 55 else: 56 raise TypeError('TdcResults.add_steps() requires a list or str') 57 58 def get_executed_steps(self): 59 return self.steps 60 61class TestSuiteReport(): 62 _testsuite = [] 63 64 def add_resultdata(self, result_data): 65 if isinstance(result_data, TestResult): 66 self._testsuite.append(result_data) 67 return True 68 69 def count_tests(self): 70 return len(self._testsuite) 71 72 def count_failures(self): 73 return sum(1 for t in self._testsuite if t.result == ResultState.fail) 74 75 def count_skips(self): 76 return sum(1 for t in self._testsuite if t.result == ResultState.skip) 77 78 def find_result(self, test_id): 79 return next((tr for tr in self._testsuite if tr.test_id == test_id), None) 80 81 def update_result(self, result_data): 82 orig = self.find_result(result_data.test_id) 83 if orig != None: 84 idx = self._testsuite.index(orig) 85 self._testsuite[idx] = result_data 86 else: 87 self.add_resultdata(result_data) 88 89 def format_tap(self): 90 ftap = "" 91 ftap += '1..{}\n'.format(self.count_tests()) 92 index = 1 93 for t in self._testsuite: 94 if t.result == ResultState.fail: 95 ftap += 'not ' 96 ftap += 'ok {} {} - {}'.format(str(index), t.test_id, t.test_name) 97 if t.result == ResultState.skip or t.result == ResultState.noresult: 98 ftap += ' # skipped - {}\n'.format(t.errormsg) 99 elif t.result == ResultState.fail: 100 if len(t.steps) > 0: 101 ftap += '\tCommands executed in this test case:' 102 for step in t.steps: 103 ftap += '\n\t\t{}'.format(step) 104 ftap += '\n\t{}'.format(t.failmsg) 105 ftap += '\n' 106 index += 1 107 return ftap 108 109 def format_xunit(self): 110 from xml.sax.saxutils import escape 111 xunit = "<testsuites>\n" 112 xunit += '\t<testsuite tests=\"{}\" skips=\"{}\">\n'.format(self.count_tests(), self.count_skips()) 113 for t in self._testsuite: 114 xunit += '\t\t<testcase classname=\"{}\" '.format(escape(t.test_id)) 115 xunit += 'name=\"{}\">\n'.format(escape(t.test_name)) 116 if t.failmsg: 117 xunit += '\t\t\t<failure>\n' 118 if len(t.steps) > 0: 119 xunit += 'Commands executed in this test case:\n' 120 for step in t.steps: 121 xunit += '\t{}\n'.format(escape(step)) 122 xunit += 'FAILURE: {}\n'.format(escape(t.failmsg)) 123 xunit += '\t\t\t</failure>\n' 124 if t.errormsg: 125 xunit += '\t\t\t<error>\n{}\n'.format(escape(t.errormsg)) 126 xunit += '\t\t\t</error>\n' 127 if t.result == ResultState.skip: 128 xunit += '\t\t\t<skipped/>\n' 129 xunit += '\t\t</testcase>\n' 130 xunit += '\t</testsuite>\n' 131 xunit += '</testsuites>\n' 132 return xunit 133