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 def __init__(self): 63 self._testsuite = [] 64 65 def add_resultdata(self, result_data): 66 if isinstance(result_data, TestResult): 67 self._testsuite.append(result_data) 68 return True 69 70 def count_tests(self): 71 return len(self._testsuite) 72 73 def count_failures(self): 74 return sum(1 for t in self._testsuite if t.result == ResultState.fail) 75 76 def count_skips(self): 77 return sum(1 for t in self._testsuite if t.result == ResultState.skip) 78 79 def find_result(self, test_id): 80 return next((tr for tr in self._testsuite if tr.test_id == test_id), None) 81 82 def update_result(self, result_data): 83 orig = self.find_result(result_data.test_id) 84 if orig != None: 85 idx = self._testsuite.index(orig) 86 self._testsuite[idx] = result_data 87 else: 88 self.add_resultdata(result_data) 89 90 def format_tap(self): 91 ftap = "" 92 ftap += '1..{}\n'.format(self.count_tests()) 93 index = 1 94 for t in self._testsuite: 95 if t.result == ResultState.fail: 96 ftap += 'not ' 97 ftap += 'ok {} {} - {}'.format(str(index), t.test_id, t.test_name) 98 if t.result == ResultState.skip or t.result == ResultState.noresult: 99 ftap += ' # skipped - {}\n'.format(t.errormsg) 100 elif t.result == ResultState.fail: 101 if len(t.steps) > 0: 102 ftap += '\tCommands executed in this test case:' 103 for step in t.steps: 104 ftap += '\n\t\t{}'.format(step) 105 ftap += '\n\t{}'.format(t.failmsg) 106 ftap += '\n' 107 index += 1 108 return ftap 109 110 def format_xunit(self): 111 from xml.sax.saxutils import escape 112 xunit = "<testsuites>\n" 113 xunit += '\t<testsuite tests=\"{}\" skips=\"{}\">\n'.format(self.count_tests(), self.count_skips()) 114 for t in self._testsuite: 115 xunit += '\t\t<testcase classname=\"{}\" '.format(escape(t.test_id)) 116 xunit += 'name=\"{}\">\n'.format(escape(t.test_name)) 117 if t.failmsg: 118 xunit += '\t\t\t<failure>\n' 119 if len(t.steps) > 0: 120 xunit += 'Commands executed in this test case:\n' 121 for step in t.steps: 122 xunit += '\t{}\n'.format(escape(step)) 123 xunit += 'FAILURE: {}\n'.format(escape(t.failmsg)) 124 xunit += '\t\t\t</failure>\n' 125 if t.errormsg: 126 xunit += '\t\t\t<error>\n{}\n'.format(escape(t.errormsg)) 127 xunit += '\t\t\t</error>\n' 128 if t.result == ResultState.skip: 129 xunit += '\t\t\t<skipped/>\n' 130 xunit += '\t\t</testcase>\n' 131 xunit += '\t</testsuite>\n' 132 xunit += '</testsuites>\n' 133 return xunit 134