xunit.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. from xml.dom.minidom import Document
  2. from prospector.formatters.base import Formatter
  3. class XunitFormatter(Formatter):
  4. """
  5. This formatter outputs messages in the Xunit xml format, which is used by several
  6. CI tools to parse output. This formatter is therefore a compatibility shim between tools built
  7. to use Xunit and prospector itself.
  8. """
  9. def render(self, summary=True, messages=True, profile=False):
  10. xml_doc = Document()
  11. testsuite_el = xml_doc.createElement("testsuite")
  12. testsuite_el.setAttribute("errors", str(self.summary["message_count"]))
  13. testsuite_el.setAttribute("failures", "0")
  14. testsuite_el.setAttribute("name", "prospector-%s" % "-".join(self.summary["tools"]))
  15. testsuite_el.setAttribute("tests", str(self.summary["message_count"]))
  16. testsuite_el.setAttribute("time", str(self.summary["time_taken"]))
  17. xml_doc.appendChild(testsuite_el)
  18. prop_el = xml_doc.createElement("properties")
  19. testsuite_el.appendChild(prop_el)
  20. sysout_el = xml_doc.createElement("system-out")
  21. sysout_el.appendChild(xml_doc.createCDATASection(""))
  22. testsuite_el.appendChild(sysout_el)
  23. syserr_el = xml_doc.createElement("system-err")
  24. syserr_el.appendChild(xml_doc.createCDATASection(""))
  25. testsuite_el.appendChild(syserr_el)
  26. for message in sorted(self.messages):
  27. testcase_el = xml_doc.createElement("testcase")
  28. testcase_el.setAttribute("name", f"{self._make_path(message.location.path)}-{message.location.line}")
  29. failure_el = xml_doc.createElement("error")
  30. failure_el.setAttribute("message", message.message.strip())
  31. failure_el.setAttribute("type", "%s Error" % message.source)
  32. template = "%(path)s:%(line)s: [%(code)s(%(source)s), %(function)s] %(message)s"
  33. cdata = template % {
  34. "path": self._make_path(message.location.path),
  35. "line": message.location.line,
  36. "source": message.source,
  37. "code": message.code,
  38. "function": message.location.function,
  39. "message": message.message.strip(),
  40. }
  41. failure_el.appendChild(xml_doc.createCDATASection(cdata))
  42. testcase_el.appendChild(failure_el)
  43. testsuite_el.appendChild(testcase_el)
  44. return xml_doc.toprettyxml()