cocotb generates results.xml file which xunit format (XML). I didn’t look that long for standard xunit schema because it doesn’t seem to exist. So, I analysed the xunit_reporter.py instead. Well, I can’t sleep anyway. so why not?!

I have to start by saying “xml.. ugh!”… writing the IPXACT parser made me hate xml forever.

The xunit report from simple_dff would look like this:

<testsuites name="results">
  <testsuite name="all" package="all">
    <property name="random_seed" value="1667509785" />
    <testcase name="dff_simple_test" classname="test_dff" file="~/examples/simple_dff/test_dff.py" lineno="20" time="0.11331820487976074" sim_time_ns="106000" ratio_time="935418.9833175886" />
  </testsuite>
</testsuites>

the module uses the python standard xml to create tree and add nodes to it.

 28 import xml.etree.ElementTree as ET
 29 from xml.etree.ElementTree import Element, SubElement

I will The root node is testsuites with attribute name=results

 32 class XUnitReporter:
 33     def __init__(self, filename="results.xml"):
 34         self.results = Element("testsuites", name="results")
 35         self.filename = filename
 36
 37     def add_testsuite(self, **kwargs):
 38         self.last_testsuite = SubElement(self.results, "testsuite", **kwargs)
 39         return self.last_testsuite
 40
 41     def add_testcase(self, testsuite=None, **kwargs):
 42         if testsuite is None:
 43             testsuite = self.last_testsuite
 44         self.last_testcase = SubElement(testsuite, "testcase", **kwargs)
 45         return self.last_testcase

So, in regression.py, tree is created and node for each package is created by calling add_testsuite, which sets last_testsuite

113         self.xunit = XUnitReporter(filename=results_filename)
114
115         self.xunit.add_testsuite(name=suite_name, package=package_name)

And to add another testcase to that testsuite, add_testcase is called with kargs to be added attributes to that node

486
487         self.xunit.add_testcase(
488             name=test.__qualname__,
489             classname=test.__module__,
490             file=inspect.getfile(test._func),
491             lineno=repr(lineno),
492             time=repr(wall_time_s),
493             sim_time_ns=repr(sim_time_ns),
494             ratio_time=repr(ratio_time),
495         )