#!/usr/bin/env python3 from enum import Enum class ResultState(Enum): noresult = -1 skip = 0 success = 1 fail = 2 class TestResult: def __init__(self, test_id="", test_name=""): self.test_id = test_id self.test_name = test_name self.result = ResultState.noresult self.failmsg = "" self.errormsg = "" self.steps = [] def set_result(self, result): if (isinstance(result, ResultState)): self.result = result return True else: raise TypeError('Unknown result type, must be type ResultState') def get_result(self): return self.result def set_errormsg(self, errormsg): self.errormsg = errormsg return True def append_errormsg(self, errormsg): self.errormsg = '{}\n{}'.format(self.errormsg, errormsg) def get_errormsg(self): return self.errormsg def set_failmsg(self, failmsg): self.failmsg = failmsg return True def append_failmsg(self, failmsg): self.failmsg = '{}\n{}'.format(self.failmsg, failmsg) def get_failmsg(self): return self.failmsg def add_steps(self, newstep): if type(newstep) == list: self.steps.extend(newstep) elif type(newstep) == str: self.steps.append(step) else: raise TypeError('TdcResults.add_steps() requires a list or str') def get_executed_steps(self): return self.steps class TestSuiteReport(): _testsuite = [] def add_resultdata(self, result_data): if isinstance(result_data, TestResult): self._testsuite.append(result_data) return True def count_tests(self): return len(self._testsuite) def count_failures(self): return sum(1 for t in self._testsuite if t.result == ResultState.fail) def count_skips(self): return sum(1 for t in self._testsuite if t.result == ResultState.skip) def find_result(self, test_id): return next((tr for tr in self._testsuite if tr.test_id == test_id), None) def update_result(self, result_data): orig = self.find_result(result_data.test_id) if orig != None: idx = self._testsuite.index(orig) self._testsuite[idx] = result_data else: self.add_resultdata(result_data) def format_tap(self): ftap = "" ftap += '1..{}\n'.format(self.count_tests()) index = 1 for t in self._testsuite: if t.result == ResultState.fail: ftap += 'not ' ftap += 'ok {} {} - {}'.format(str(index), t.test_id, t.test_name) if t.result == ResultState.skip or t.result == ResultState.noresult: ftap += ' # skipped - {}\n'.format(t.errormsg) elif t.result == ResultState.fail: if len(t.steps) > 0: ftap += '\tCommands executed in this test case:' for step in t.steps: ftap += '\n\t\t{}'.format(step) ftap += '\n\t{}'.format(t.failmsg) ftap += '\n' index += 1 return ftap def format_xunit(self): from xml.sax.saxutils import escape xunit = "<testsuites>\n" xunit += '\t<testsuite tests=\"{}\" skips=\"{}\">\n'.format(self.count_tests(), self.count_skips()) for t in self._testsuite: xunit += '\t\t<testcase classname=\"{}\" '.format(escape(t.test_id)) xunit += 'name=\"{}\">\n'.format(escape(t.test_name)) if t.failmsg: xunit += '\t\t\t<failure>\n' if len(t.steps) > 0: xunit += 'Commands executed in this test case:\n' for step in t.steps: xunit += '\t{}\n'.format(escape(step)) xunit += 'FAILURE: {}\n'.format(escape(t.failmsg)) xunit += '\t\t\t</failure>\n' if t.errormsg: xunit += '\t\t\t<error>\n{}\n'.format(escape(t.errormsg)) xunit += '\t\t\t</error>\n' if t.result == ResultState.skip: xunit += '\t\t\t<skipped/>\n' xunit += '\t\t</testcase>\n' xunit += '\t</testsuite>\n' xunit += '</testsuites>\n' return xunit