blob: 540ef5697473aeadee9b62baf12d6bedc72fdeda [file] [log] [blame]
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +00001"""Simple xunit results file creator utility."""
2# Copyright (c) 2020-2022, ARM Limited.
3# SPDX-License-Identifier: Apache-2.0
Eric Kunzee5e26762020-10-13 16:11:07 -07004import xml.etree.ElementTree as ET
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +00005from xml.dom import minidom
Eric Kunzee5e26762020-10-13 16:11:07 -07006
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +00007
8class xunit_results:
9 """Xunit results writer."""
10
11 def __init__(self):
12 """Initialize results."""
13 self.name = "testsuites"
Eric Kunzee5e26762020-10-13 16:11:07 -070014 self.suites = []
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000015
Eric Kunzee5e26762020-10-13 16:11:07 -070016 def create_suite(self, name):
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000017 """Create xunit suite for results."""
Eric Kunzee5e26762020-10-13 16:11:07 -070018 s = xunit_suite(name)
19 self.suites.append(s)
20 return s
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000021
Eric Kunzee5e26762020-10-13 16:11:07 -070022 def write_results(self, filename):
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000023 """Write the results to the appropriate suites."""
Eric Kunzee5e26762020-10-13 16:11:07 -070024 suites = ET.Element(self.name)
25 tree = ET.ElementTree(suites)
26 for s in self.suites:
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000027 testsuite = ET.SubElement(
28 suites, "testsuite", {"name": s.name, "errors": "0"}
29 )
Eric Kunzee5e26762020-10-13 16:11:07 -070030 tests = 0
31 failures = 0
32 skip = 0
33 for t in s.tests:
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000034 test = ET.SubElement(
35 testsuite,
36 "testcase",
37 {"name": t.name, "classname": t.classname, "time": t.time},
38 )
Eric Kunzee5e26762020-10-13 16:11:07 -070039 tests += 1
40 if t.skip:
41 skip += 1
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000042 ET.SubElement(test, "skipped", {"type": "Skipped test"})
Eric Kunzee5e26762020-10-13 16:11:07 -070043 if t.fail:
44 failures += 1
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000045 fail = ET.SubElement(test, "failure", {"type": "Test failed"})
Eric Kunzee5e26762020-10-13 16:11:07 -070046 fail.text = t.fail
47 if t.sysout:
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000048 sysout = ET.SubElement(test, "system-out")
Eric Kunzee5e26762020-10-13 16:11:07 -070049 sysout.text = t.sysout
50 if t.syserr:
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000051 syserr = ET.SubElement(test, "system-err")
Eric Kunzee5e26762020-10-13 16:11:07 -070052 syserr.text = t.syserr
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000053 testsuite.attrib["tests"] = str(tests)
54 testsuite.attrib["failures"] = str(failures)
55 testsuite.attrib["skip"] = str(skip)
56 xmlstr = minidom.parseString(ET.tostring(tree.getroot())).toprettyxml(
57 indent=" "
58 )
59 with open(filename, "w") as f:
60 f.write(xmlstr)
Eric Kunzee5e26762020-10-13 16:11:07 -070061
62
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000063class xunit_suite:
64 """Xunit suite for test results."""
65
Eric Kunzee5e26762020-10-13 16:11:07 -070066 def __init__(self, name):
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000067 """Initialize suite."""
Eric Kunzee5e26762020-10-13 16:11:07 -070068 self.name = name
69 self.tests = []
70
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000071
72# classname should be of the form suite.class/subclass/subclass2/...
73# You can have an unlimited number of subclasses in this manner
74
75
76class xunit_test:
77 """Xunit test result."""
78
Eric Kunzee5e26762020-10-13 16:11:07 -070079 def __init__(self, name, classname=None):
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000080 """Initialize test."""
Eric Kunzee5e26762020-10-13 16:11:07 -070081 self.name = name
82 if classname:
83 self.classname = classname
84 else:
85 self.classname = name
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000086 self.time = "0.000"
Eric Kunzee5e26762020-10-13 16:11:07 -070087 self.fail = None
88 self.skip = False
89 self.sysout = None
90 self.syserr = None
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000091
Eric Kunzee5e26762020-10-13 16:11:07 -070092 def failed(self, text):
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000093 """Set test failed information."""
Eric Kunzee5e26762020-10-13 16:11:07 -070094 self.fail = text
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000095
Eric Kunzee5e26762020-10-13 16:11:07 -070096 def skipped(self):
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +000097 """Set test as skipped."""
Eric Kunzee5e26762020-10-13 16:11:07 -070098 self.skip = True
99
100
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +0000101if __name__ == "__main__":
102 # Simple test
Eric Kunzee5e26762020-10-13 16:11:07 -0700103 r = xunit_results()
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +0000104 s = r.create_suite("selftest")
105 for i in range(0, 10):
106 t = xunit_test("atest" + str(i), "selftest")
Eric Kunzee5e26762020-10-13 16:11:07 -0700107 if i == 3:
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +0000108 t.failed("Unknown failure foo")
Eric Kunzee5e26762020-10-13 16:11:07 -0700109 if i == 7:
110 t.skipped()
111 s.tests.append(t)
Jeremy Johnsonbe1a9402021-12-15 17:14:56 +0000112 r.write_results("foo.xml")