summaryrefslogtreecommitdiff
path: root/tests/plugins.py
blob: 4e7af97aec3533c37718358356b4f8568b2a51b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import traceback
from nose.plugins import Plugin
from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin


class MarkdownSyntaxError(Exception):
    pass


class Markdown(ErrorClassPlugin):
    """ Add MarkdownSyntaxError and ensure proper formatting. """
    mdsyntax = ErrorClass(
        MarkdownSyntaxError,
        label='MarkdownSyntaxError',
        isfailure=True
    )
    enabled = True

    def configure(self, options, conf):
        self.conf = conf

    def addError(self, test, err):
        """ Ensure other plugins see the error by returning nothing here. """
        pass

    def formatError(self, test, err):
        """ Remove unnessecary and unhelpful traceback from error report. """
        et, ev, tb = err
        if et.__name__ == 'MarkdownSyntaxError':
            return et, ev, ''
        return err


def escape(html):
    """ Escape HTML for display as source within HTML. """
    html = html.replace('&', '&')
    html = html.replace('<', '&lt;')
    html = html.replace('>', '&gt;')
    return html


class HtmlOutput(Plugin):
    """Output test results as ugly, unstyled html. """

    name = 'html-output'
    score = 2  # run late
    enabled = True

    def __init__(self):
        super(HtmlOutput, self).__init__()
        self.html = [
            '<html><head>',
            '<title>Test output</title>',
            '</head><body>'
        ]

    def configure(self, options, conf):
        self.conf = conf

    def addSuccess(self, test):
        self.html.append('<span>ok</span>')

    def addError(self, test, err):
        err = self.formatErr(err)
        self.html.append('<span>ERROR</span>')
        self.html.append('<pre>%s</pre>' % escape(err))

    def addFailure(self, test, err):
        err = self.formatErr(err)
        self.html.append('<span>FAIL</span>')
        self.html.append('<pre>%s</pre>' % escape(err))

    def finalize(self, result):
        self.html.append('<div>')
        self.html.append(
            "Ran %d test%s" %
            (result.testsRun, result.testsRun != 1 and "s" or "")
        )
        self.html.append('</div>')
        self.html.append('<div>')
        if not result.wasSuccessful():
            self.html.extend(['<span>FAILED (',
                              'failures=%d ' % len(result.failures),
                              'errors=%d' % len(result.errors)])
            for cls in list(result.errorClasses.keys()):
                storage, label, isfail = result.errorClasses[cls]
                if len(storage):
                    self.html.append(' %ss=%d' % (label, len(storage)))
            self.html.append(')</span>')
        else:
            self.html.append('OK')
        self.html.append('</div></body></html>')
        f = open('test-output.html', 'w')
        for l in self.html:
            f.write(l)
        f.close()

    def formatErr(self, err):
        exctype, value, tb = err
        if not isinstance(value, exctype):
            value = exctype(value)
        return ''.join(traceback.format_exception(exctype, value, tb))

    def startContext(self, ctx):
        try:
            n = ctx.__name__
        except AttributeError:
            n = str(ctx).replace('<', '').replace('>', '')
        self.html.extend(['<fieldset>', '<legend>', n, '</legend>'])
        try:
            path = ctx.__file__.replace('.pyc', '.py')
            self.html.extend(['<div>', path, '</div>'])
        except AttributeError:
            pass

    def stopContext(self, ctx):
        self.html.append('</fieldset>')

    def startTest(self, test):
        self.html.extend([
            '<div><span>',
            test.shortDescription() or str(test),
            '</span>'
        ])

    def stopTest(self, test):
        self.html.append('</div>')