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