From dd509fb70489c8be2f097f1b0d511657d1c061ce Mon Sep 17 00:00:00 2001 From: Luis Rodrigues Date: Sun, 1 Mar 2015 18:09:01 +0000 Subject: [PATCH] added xunit formater support --- prospector/formatters/__init__.py | 3 +- prospector/formatters/xunit.py | 60 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 prospector/formatters/xunit.py diff --git a/prospector/formatters/__init__.py b/prospector/formatters/__init__.py index 89ed0f70..262c53bc 100644 --- a/prospector/formatters/__init__.py +++ b/prospector/formatters/__init__.py @@ -1,4 +1,4 @@ -from prospector.formatters import json, text, grouped, emacs, yaml, pylint +from prospector.formatters import json, text, grouped, emacs, yaml, pylint, xunit __all__ = ( @@ -13,4 +13,5 @@ 'emacs': emacs.EmacsFormatter, 'yaml': yaml.YamlFormatter, 'pylint': pylint.PylintFormatter, + 'xunit': xunit.XunitFormatter, } diff --git a/prospector/formatters/xunit.py b/prospector/formatters/xunit.py new file mode 100644 index 00000000..09c8b6f0 --- /dev/null +++ b/prospector/formatters/xunit.py @@ -0,0 +1,60 @@ +import os +import re +from prospector.formatters.base import Formatter +from xml.dom.minidom import Document + + +class XunitFormatter(Formatter): + + """ + This formatter outputs messages in the Xunit xml format, which is used by several + CI tools to parse output. This formatter is therefore a compatability shim between tools built + to use Xunit and prospector itself. + """ + + def render(self, summary=True, messages=True, profile=False): + xml_doc = Document() + + testsuite_el = xml_doc.createElement('testsuite') + testsuite_el.setAttribute('errors', str(self.summary['message_count'])) + testsuite_el.setAttribute('failures', '0') + testsuite_el.setAttribute('name', 'prospector-%s'%'-'.join(self.summary['tools'])) + testsuite_el.setAttribute('tests', str(self.summary['message_count'])) + testsuite_el.setAttribute('time', str(self.summary['time_taken'])) + xml_doc.appendChild(testsuite_el) + + prop_el = xml_doc.createElement('properties') + testsuite_el.appendChild(prop_el) + + sysout_el = xml_doc.createElement('system-out') + sysout_el.appendChild(xml_doc.createCDATASection('')) + testsuite_el.appendChild(sysout_el) + + syserr_el = xml_doc.createElement('system-err') + syserr_el.appendChild(xml_doc.createCDATASection('')) + testsuite_el.appendChild(syserr_el) + + for message in sorted(self.messages): + testcase_el = xml_doc.createElement('testcase') + testcase_el.setAttribute('name', '%s-%s' % (message.location.path, message.location.line)) + + failure_el = xml_doc.createElement('error') + failure_el.setAttribute('message', message.message.strip()) + failure_el.setAttribute('type', '%s Error' % message.source) + template = '%(path)s:%(line)s: [%(code)s(%(source)s), %(function)s] %(message)s' + cdata = template % { + 'path': message.location.path, + 'line': message.location.line, + 'source': message.source, + 'code': message.code, + 'function': message.location.function, + 'message': message.message.strip() + } + failure_el.appendChild(xml_doc.createCDATASection(cdata)) + + testcase_el.appendChild(failure_el) + + testsuite_el.appendChild(testcase_el) + + return xml_doc.toprettyxml(encoding='utf-8') +