summaryrefslogtreecommitdiff
path: root/coverage/xmlreport.py
diff options
context:
space:
mode:
Diffstat (limited to 'coverage/xmlreport.py')
-rw-r--r--coverage/xmlreport.py74
1 files changed, 46 insertions, 28 deletions
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py
index 0fe43712..17d9fd5f 100644
--- a/coverage/xmlreport.py
+++ b/coverage/xmlreport.py
@@ -14,23 +14,26 @@ def rate(hit, num):
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)
-
+
self.packages = None
self.xml_out = None
+ self.arcs = coverage.data.has_arcs()
- def report(self, morfs, omit_prefixes=None, outfile=None):
+ def report(self, morfs, omit_prefixes=None, include_prefixes=None,
+ outfile=None
+ ):
"""Generate a Cobertura-compatible XML report for `morfs`.
-
- `morfs` is a list of modules or filenames. `omit_prefixes` is a list
- of strings, prefixes of modules to omit from the report.
-
+
+ `morfs` is a list of modules or filenames.
+
+ See `coverage.report()` for other arguments.
+
"""
# Initial setup.
outfile = outfile or sys.stdout
- self.find_code_units(morfs, omit_prefixes)
# Create the DOM that will store the data.
impl = xml.dom.minidom.getDOMImplementation()
@@ -39,8 +42,9 @@ class XmlReporter(Reporter):
"http://cobertura.sourceforge.net/xml/coverage-03.dtd"
)
self.xml_out = impl.createDocument(None, "coverage", docType)
- xcoverage = self.xml_out.documentElement
+ # Write header stuff.
+ xcoverage = self.xml_out.documentElement
xcoverage.setAttribute("version", __version__)
xcoverage.setAttribute("timestamp", str(int(time.time()*1000)))
xcoverage.appendChild(self.xml_out.createComment(
@@ -48,13 +52,17 @@ class XmlReporter(Reporter):
))
xpackages = self.xml_out.createElement("packages")
xcoverage.appendChild(xpackages)
- self.packages = {}
- self.report_files(self.xml_file, morfs, omit_prefixes=omit_prefixes)
+ # Call xml_file for each file in the data.
+ self.packages = {}
+ self.report_files(
+ self.xml_file, morfs, omit_prefixes=omit_prefixes,
+ include_prefixes=include_prefixes
+ )
lnum_tot, lhits_tot = 0, 0
bnum_tot, bhits_tot = 0, 0
-
+
# Populate the XML DOM with the package info.
for pkg_name, pkg_data in self.packages.items():
class_elts, lhits, lnum, bhits, bnum = pkg_data
@@ -73,16 +81,16 @@ class XmlReporter(Reporter):
lhits_tot += lhits
bnum_tot += bnum
bhits_tot += bhits
-
+
xcoverage.setAttribute("line-rate", str(rate(lhits_tot, lnum_tot)))
xcoverage.setAttribute("branch-rate", str(rate(bhits_tot, bnum_tot)))
-
+
# Use the DOM to write the output file.
outfile.write(self.xml_out.toprettyxml())
def xml_file(self, cu, analysis):
"""Add to the XML report for a single file."""
-
+
# Create the 'lines' and 'package' XML elements, which
# are populated later. Note that a package == a directory.
dirname, fname = os.path.split(cu.name)
@@ -101,26 +109,36 @@ class XmlReporter(Reporter):
xclass.setAttribute("filename", cu.name + ext)
xclass.setAttribute("complexity", "0.0")
+ branch_lines = analysis.branch_lines()
+
# For each statement, create an XML 'line' element.
for line in analysis.statements:
- l = self.xml_out.createElement("line")
- l.setAttribute("number", str(line))
+ xline = self.xml_out.createElement("line")
+ xline.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.
- l.setAttribute("hits", str(int(not line in analysis.missing)))
+ # Q: can we get info about the number of times a statement is
+ # executed? If so, that should be recorded here.
+ xline.setAttribute("hits", str(int(not line in analysis.missing)))
- # Q: can we get info about whether this statement
- # is a branch? If so, that data should be
- # used here.
- #l.setAttribute("branch", "false")
- xlines.appendChild(l)
+ if self.arcs:
+ if line in branch_lines:
+ xline.setAttribute("branch", "true")
+ xlines.appendChild(xline)
class_lines = 1.0 * len(analysis.statements)
class_hits = class_lines - len(analysis.missing)
- class_branches = 0.0
- class_branch_hits = 0.0
+
+ if self.arcs:
+ # We assume here that every branch line has 2 exits, which is
+ # usually true. In theory, though, we could have a branch line
+ # with more exits..
+ class_branches = 2.0 * len(branch_lines)
+ missed_branch_targets = analysis.missing_branch_arcs().values()
+ missing_branches = sum([len(b) for b in missed_branch_targets])
+ class_branch_hits = class_branches - missing_branches
+ else:
+ class_branches = 0.0
+ class_branch_hits = 0.0
# Finalize the statistics that are collected in the XML DOM.
line_rate = rate(class_hits, class_lines)