aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2011-08-05 21:55:12 +0200
committerMichał Górny <mgorny@gentoo.org>2011-08-05 21:55:12 +0200
commit6c21f8b452e8454fc56a0eda654b54a299f29e9c (patch)
tree8dcd83519772d12cf8d9ee9357ad354ec8a3c0a9
parentPortage: quieter unmerge, always remove build dir. (diff)
downloadpms-test-suite-6c21f8b452e8454fc56a0eda654b54a299f29e9c.tar.gz
pms-test-suite-6c21f8b452e8454fc56a0eda654b54a299f29e9c.tar.bz2
pms-test-suite-6c21f8b452e8454fc56a0eda654b54a299f29e9c.zip
Add the HTML output module.
-rw-r--r--pmstestsuite/output/__init__.py3
-rw-r--r--pmstestsuite/output/html.py182
2 files changed, 184 insertions, 1 deletions
diff --git a/pmstestsuite/output/__init__.py b/pmstestsuite/output/__init__.py
index cef7ab8..0c7c8be 100644
--- a/pmstestsuite/output/__init__.py
+++ b/pmstestsuite/output/__init__.py
@@ -83,5 +83,6 @@ def get_output_modules():
"""
from pmstestsuite.output.cli import CLIOutput
+ from pmstestsuite.output.html import HTMLOutput
- return (CLIOutput,)
+ return (CLIOutput, HTMLOutput)
diff --git a/pmstestsuite/output/html.py b/pmstestsuite/output/html.py
new file mode 100644
index 0000000..5842eb9
--- /dev/null
+++ b/pmstestsuite/output/html.py
@@ -0,0 +1,182 @@
+# vim:fileencoding=utf-8
+# (c) 2011 Michał Górny <mgorny@gentoo.org>
+# Released under the terms of the 2-clause BSD license.
+
+from collections import defaultdict
+
+from pmstestsuite.output import OutputModule
+
+class HTMLOutput(OutputModule):
+ name = 'html'
+
+ def __init__(self, path = None):
+ if path is None:
+ path = 'pms-test-suite-output.html'
+ self._path = path
+
+ _htmlheader = '''<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>PMS Test Suite test results</title>
+ <style type="text/css">
+ table {
+ margin: 0 auto;
+ border: 1px solid;
+ }
+
+ th, td {
+ padding: .1em 1em;
+ border: 1px solid;
+ }
+
+ .value {
+ font-family: monospace;
+ text-align: center;
+ }
+
+ .good {
+ background: #88e888;
+ }
+
+ .bad {
+ background: #e88888;
+ }
+ </style>
+ </head>
+ <body>
+ <table>'''
+
+ _htmlfooter = '''
+ </table>
+ </body>
+</html>'''
+
+ def __call__(self, allresults, verbose = False):
+ mypms = []
+
+ def _results_by_test(allresults):
+ ret = defaultdict(lambda: defaultdict(lambda: None))
+ for pm, results in allresults.items():
+ mypms.append(pm)
+ for t, r in results.items():
+ ret[t][pm] = r
+ return ret
+
+ def _results_by_class(reorderedresults):
+ ret = defaultdict(dict)
+ for t, r in reorderedresults.items():
+ ret[t.__class__.__name__][t] = r
+ return ret
+
+ def _sorted_pms(pms):
+ for pm in sorted(pms, key = lambda pm: mypms.index(pm)):
+ yield (pm, pms[pm])
+
+ class HTMLElem(object):
+ _elem = 'td'
+
+ def __init__(self, text):
+ self._attrs = []
+ self._text = text
+
+ def set_rowspan(self, rowspan):
+ if rowspan != 1:
+ self._attrs.append('rowspan="%d"' % rowspan)
+
+ def __str__(self):
+ return '<%s>%s</%s>' % (' '.join([self._elem] + self._attrs),
+ self._text, self._elem)
+
+ class TH(HTMLElem):
+ _elem = 'th'
+
+ def __init__(self, text, colspan = 1):
+ HTMLElem.__init__(self, text)
+ self._colspan = colspan
+ if colspan != 1:
+ self._attrs.append('colspan="%d"' % colspan)
+
+ class ValCell(HTMLElem):
+ _color_class = ''
+
+ def __init__(self, text):
+ HTMLElem.__init__(self, text)
+ self._attrs.append('class="value %s"' % self._color_class)
+
+ class ColorValCell(ValCell):
+ def __init__(self, text, cond):
+ self._color_class = 'good' if cond else 'bad'
+ ValCell.__init__(self, text)
+
+ class BoolCell(ValCell):
+ def __init__(self, cond):
+ self._color_class = 'good' if cond else 'bad'
+ ValCell.__init__(self, 'OK' if cond else 'FAIL')
+
+ class NoCell(HTMLElem):
+ def __init__(self):
+ pass
+
+ def __str__(self):
+ return ''
+
+ ret = True
+ results = _results_by_test(allresults)
+ table = defaultdict(lambda: defaultdict(lambda: None))
+
+ table[0][0] = TH('Test name')
+ table[0][1] = TH('EAPI')
+ table[0][2] = TH('Assertion')
+ table[0][3] = TH('Expected')
+ for i, pm in enumerate(mypms):
+ table[0][4 + i*3] = TH(pm.name, colspan = 3)
+ table[0][5 + i*3] = NoCell()
+ table[1][4 + i*3] = TH('Actual')
+ table[1][5 + i*3] = TH('Result')
+ maxcol = 6 + i*3
+
+ row = 2
+ for cl, tests in _results_by_class(results).items():
+ table[row][0] = cl
+ for t, pms in tests.items():
+ table[row][1] = t.eapi
+ test_asserts = []
+ col = 4
+ for pm, r in _sorted_pms(pms):
+ table[row][col+1] = BoolCell(r)
+ for a in r.assertions:
+ if a.name not in test_asserts:
+ test_asserts.append(a.name)
+ crow = row + test_asserts.index(a.name)
+ table[crow][2] = a.name
+ table[crow][3] = ValCell(a.expected)
+ else:
+ crow = row + test_asserts.index(a.name)
+
+ table[crow][col] = ColorValCell(a.actual, a)
+ col += 2
+ row += len(test_asserts)
+
+ f = open(self._path, 'w')
+ f.write(self._htmlheader)
+ for y in range(0, row):
+ f.write('<tr>')
+ for x in range(0, maxcol):
+ cell = table[y][x]
+ if cell is not None:
+ rowspan = 1
+ for y2 in range(y + 1, row):
+ if table[y2][x] is None:
+ rowspan += 1
+ else:
+ break
+
+ if not isinstance(cell, HTMLElem):
+ cell = HTMLElem(cell)
+ cell.set_rowspan(rowspan)
+ f.write(str(cell))
+ f.write('</tr>')
+ f.write(self._htmlfooter)
+ f.close()
+
+ return ret