~ubuntu-branches/ubuntu/vivid/pyjunitxml/vivid

« back to all changes in this revision

Viewing changes to junitxml/__init__.py

  • Committer: Bazaar Package Importer
  • Author(s): Robert Collins
  • Date: 2009-09-20 17:19:22 UTC
  • Revision ID: james.westby@ubuntu.com-20090920171922-e2vwr52quh24jxc9
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
#  junitxml: extensions to Python unittest to get output junitxml
 
3
#  Copyright (C) 2009 Robert Collins <robertc@robertcollins.net>
 
4
#
 
5
#  Copying permitted under the LGPL-3 licence, included with this library.
 
6
 
 
7
"""unittest compatible JUnit XML output."""
 
8
 
 
9
 
 
10
import datetime
 
11
import unittest
 
12
from xml.sax.saxutils import escape
 
13
 
 
14
 
 
15
def test_suite():
 
16
    import junitxml.tests
 
17
    return junitxml.tests.test_suite()
 
18
 
 
19
 
 
20
class JUnitXmlResult(unittest.TestResult):
 
21
    """A TestResult which outputs JUnit compatible XML."""
 
22
    
 
23
    def __init__(self, stream):
 
24
        """Create a JUnitXmlResult.
 
25
 
 
26
        :param stream: A stream to write results to. Note that due to the
 
27
            nature of JUnit XML output, nnothing will be written to the stream
 
28
            until stopTestRun() is called.
 
29
        """
 
30
        super(JUnitXmlResult, self).__init__()
 
31
        self._stream = stream
 
32
        self._results = []
 
33
        self._set_time = None
 
34
        self._test_start = None
 
35
        self._run_start = None
 
36
 
 
37
    def _super(self):
 
38
        return super(JUnitXmlResult, self)
 
39
 
 
40
    def startTestRun(self):
 
41
        """Start a test run."""
 
42
        self._run_start = self._now()
 
43
 
 
44
    def _now(self):
 
45
        if self._set_time is not None:
 
46
            return self._set_time
 
47
        else:
 
48
            return datetime.datetime.utcnow()
 
49
 
 
50
    def time(self, a_datetime):
 
51
        self._set_time = a_datetime
 
52
 
 
53
    def startTest(self, test):
 
54
        self._test_start = self._now()
 
55
 
 
56
    def _duration(self, from_datetime):
 
57
        delta = self._now() - from_datetime
 
58
        seconds = delta.days * 3600*24 + delta.seconds
 
59
        return seconds + 0.000001 * delta.microseconds
 
60
 
 
61
    def _test_case_string(self, test):
 
62
        duration = self._duration(self._test_start)
 
63
        prefix_suffix = test.id().rsplit('.', 1)
 
64
        if len(prefix_suffix) == 1:
 
65
            classname = ""
 
66
            name = prefix_suffix[0]
 
67
        else:
 
68
            classname = prefix_suffix[0]
 
69
            name = prefix_suffix[1]
 
70
        self._results.append('<testcase classname="%s" name="%s" '
 
71
            'time="%0.3f"' % (escape(classname), escape(name), duration))
 
72
 
 
73
    def stopTestRun(self):
 
74
        """Stop a test run.
 
75
 
 
76
        This allows JUnitXmlResult to output the XML representation of the test
 
77
        run.
 
78
        """
 
79
        duration = self._duration(self._run_start)
 
80
        self._stream.write('<testsuite errors="%d" failures="%d" name="" tests="0" time="%0.3f">\n' % (len(self.errors), len(self.failures), duration))
 
81
        self._stream.write(''.join(self._results))
 
82
        self._stream.write('</testsuite>\n')
 
83
 
 
84
    def addError(self, test, error):
 
85
        self._super().addError(test, error)
 
86
        self._test_case_string(test)
 
87
        self._results.append('>\n')
 
88
        self._results.append('<error type="%s.%s">%s</error>\n</testcase>\n'% (escape(error[0].__module__), escape(error[0].__name__), escape(self._exc_info_to_string(error, test))))
 
89
 
 
90
    def addFailure(self, test, error):
 
91
        self._super().addFailure(test, error)
 
92
        self._test_case_string(test)
 
93
        self._results.append('>\n')
 
94
        self._results.append('<failure type="%s.%s">%s</failure>\n</testcase>\n'% (escape(error[0].__module__), escape(error[0].__name__), escape(self._exc_info_to_string(error, test))))
 
95
 
 
96
    def addSuccess(self, test):
 
97
        self._super().addSuccess(test)
 
98
        self._test_case_string(test)
 
99
        self._results.append(' />\n')
 
100
 
 
101
    def addSkip(self, test, reason):
 
102
        self._super().addSkip(test, reason)
 
103
        self._test_case_string(test)
 
104
        self._results.append('>\n')
 
105
        self._results.append('<skip type="%s.%s">%s</skip>\n</testcase>\n'% (escape(error[0].__module__), escape(error[0].__name__), escape(reason)))
 
106
 
 
107
    def addUnexpectedSuccess(self, test):
 
108
        self._super().addUnexpectedSuccess(test, error)
 
109
        self._test_case_string(test)
 
110
        self._results.append(' />\n')
 
111
 
 
112
    def addExpectedFailure(self, test, error):
 
113
        self._super().addExpectedFailure(test, error)
 
114
        self._test_case_string(test)
 
115
        self._results.append('>\n')
 
116
        self._results.append('<failure type="%s.%s">%s</failure>\n</testcase>\n'% (escape(error[0].__module__), escape(error[0].__name__), escape(self._exc_info_to_string(error, test))))
 
117