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
|
"""Cobertura reporting for coverage.py"""
import os, sys
import xml.dom.minidom
from coverage.report import Reporter
class XmlReporter(Reporter):
"""A reporter for writing Cobertura-style XML coverage results."""
def __init__(self, coverage, ignore_errors=False):
super(XmlReporter, self).__init__(coverage, ignore_errors)
def report(self, morfs, omit_prefixes=None, outfile=None):
"""Generate a Cobertura report for `morfs`.
`morfs` is a list of modules or filenames. `directory` is where to put
the Cobertura XML file. `omit_prefixes` is a list of strings, prefixes of
modules to omit from the report.
"""
# Initial setup.
if not outfile:
outfile = sys.stdout
self.find_code_units(morfs, omit_prefixes)
# Create the DOM that will store the data.
impl = xml.dom.minidom.getDOMImplementation()
docType = impl.createDocumentType(
"coverage", None,
"http://cobertura.sourceforge.net/xml/coverage-03.dtd" )
doc = impl.createDocument(None, "coverage", docType)
root = doc.documentElement
packageXml = doc.createElement("packages")
root.appendChild(packageXml)
packages = {}
errors = False
for cu in self.code_units:
# Create the 'lines' and 'package' XML elements, which
# are populated later. Note that a package == a directory.
(dir, fname) = os.path.split(cu.name)
print "HERE",dir,":",fname
if dir is '':
dir = '.'
package = packages.setdefault(
dir, [ doc.createElement("package"), {},
0, 0, 0, 0 ] )
c = doc.createElement("class")
lines = doc.createElement("lines")
c.appendChild(lines)
className = fname.replace('.', '_')
c.setAttribute("name", className)
c.setAttribute("filename", cu.name)
c.setAttribute("complexity", "0.0")
try:
statements, _, missing, readable = self.coverage._analyze(cu)
# For each statement, create an XML 'line' element.
for line in statements:
l = doc.createElement("line")
l.setAttribute("number", str(line))
# Q: can we get info about the number of times
# a statement is executed? If so, that should be
# recorded here.
if not line in missing:
l.setAttribute("hits", str(1))
# Q: can we get info about whether this statement
# is a branch? If so, that data should be
# used here.
l.setAttribute("branch", "false")
lines.appendChild(l)
class_lines = 1.0*len(statements)
class_hits = class_lines - len(missing)
class_branches = 0.0
class_branch_hits = 0.0
# Finalize the statistics that are collected
# in the XML DOM.
c.setAttribute("line-rate", str(class_hits / (class_lines or 1.0)))
c.setAttribute( "branch-rate", str(class_branch_hits / (class_branches or 1.0)) )
package[1][className] = c
package[2] += class_hits
package[3] += class_lines
package[4] += class_branch_hits
package[5] += class_branches
except KeyboardInterrupt: #pragma: no cover
raise
except:
if not self.ignore_errors:
typ, msg = sys.exc_info()[:2]
fmt_err = "%s %s: %s\n"
outfile.write(fmt_err % (cu.name, typ.__name__, msg))
errors=True
# Don't write the XML data if we've encountered errors.
if errors:
return
# Populate the XML DOM with the package info.
for packageName, packageData in packages.items():
package = packageData[0];
packageXml.appendChild(package)
classes = doc.createElement("classes")
package.appendChild(classes)
classNames = packageData[1].keys()
classNames.sort()
for className in classNames:
classes.appendChild(packageData[1][className])
package.setAttribute("name", packageName.replace(os.sep, '.'))
package.setAttribute("line-rate", str(packageData[2]/(packageData[3] or 1.0)))
package.setAttribute( "branch-rate", str(packageData[4] / (packageData[5] or 1.0) ))
package.setAttribute("complexity", "0.0")
# Use the DOM to write the output file.
outfile.write(doc.toprettyxml())
|