Convert nosetests xml to html (hack)

Want to see the output of your nosetests run in a format that you can hand to someone non-technical (who doesn't mind it being ugly)?  Here's a little script to convert the result of nosetests --with-xunit to an ugly, but functional HTML file.  I can't say I really see this as a long-term solution, as it would seem better to just write a proper plug-in for nose, but I was asked for a solution ASAP and I want to get to sleep tonight :) .

#! /usr/bin/env python
from xml.etree import ElementTree as ET
import glob, os, datetime, subprocess, sys
import kid, logging, sys
log = logging.getLogger( 'convert' )

def main(name='nosetests.xml'):
doc = ET.parse( name )
suite = doc.getroot()
new = os.path.splitext( name )[0] + '.html'

serial = kid.XHTMLSerializer( decl=True )
template = kid.Template(
file='template.kid',
date=datetime.datetime.now().isoformat(),
report = suite,
)
data = template.serialize( output=serial )
open( new, 'w').write( data )

if __name__ == "__main__":
main( *sys.argv[1:] )

Which uses the following kid template...

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#">
<div py:def="contents( docbook )" py:strip="">${docbook.text}${[convert(x) for x in docbook]}</div>
<div py:def="convert( docbook )" py:strip="">
<?python
approach = 'div'
if '}' in docbook.tag:
basetag = docbook.tag.split( "}" )[1]
else:
basetag = docbook.tag
approach_set = {
'testsuite':'testsuite',
'testcase': 'testcase',
'error':'pre',
'failure':'pre',
}
#print "tag %s approach %r"%( docbook.tag, approach )
approach = approach_set.get( basetag, 'div' )
if approach == 'testcase':
if len(docbook):
case_class = docbook[0].tag
else:
case_class = 'success'
else:
case_class = None
?>
<div py:if="approach=='testsuite'" class="${basetag}">
<h1>Test Run Report</h1>
<table class="test-summary"><thead><tr>
<th>Total</th>
<th>Test Errors</th>
<th>Failures/Regressions</th>
<th>Skipped</th>
</tr></thead><tbody><tr>
<td>${docbook.get('tests')}</td>
<td>${docbook.get('errors')}</td>
<td>${docbook.get('failures')}</td>
<td>${docbook.get('skip')}</td>
</tr></tbody></table>
${contents(docbook)}
</div>
<div py:if="approach=='testcase'" class="${basetag} ${case_class}">
<h2 py:if="not len(docbook)">${docbook.get( 'name')} (success)</h2>
<h2 py:if="len(docbook)">${docbook.get( 'name')}</h2>
<div py:if="len(docbook)" class="test-case-content">
${contents(docbook)}
</div>
</div>

<div py:if="approach=='div'" class="${basetag}">${contents(docbook)} Hello</div>
<span py:if="approach=='span'" class="${basetag}">${contents(docbook)}</span>
<pre py:if="approach=='pre'" class="${basetag}">${contents(docbook)}</pre>
<div py:if="approach=='expand'" py:strip="">${[convert(x) for x in docbook]}</div>
<div py:if="approach=='copy'" py:strip="">${docbook}</div>
<h2 py:if="approach=='heading'" class="${basetag}">${contents(docbook)}</h2>
<dd py:if="approach=='dd'" class="${basetag}">${contents(docbook)}</dd>
<dl py:if="approach=='dl'" class="${basetag}">${contents(docbook)}</dl>
<dt py:if="approach=='dt'" class="${basetag}">${contents(docbook)}</dt>
${(docbook.tail or '').strip()}
</div>

<head>
<title>Test Run Report</title>
<style type="text/css">
.testcase {
font-size: smaller;
}
.testcase h2 {
font-size: smaller;
}
.test-case-content {
margin-left: 2em;
}
.error {
color: #3030cc;
}
.failure {
color: #cc0000;
}
.success {
color: #cccccc;
}
</style>
</head>
<body>
${convert( report )}
</body>
</html>

Comments

Comments are closed.

Pingbacks

Pingbacks are closed.