diff options
Diffstat (limited to 'coverage/xmlreport.py')
-rw-r--r-- | coverage/xmlreport.py | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py index 996f19a2..b60cecd2 100644 --- a/coverage/xmlreport.py +++ b/coverage/xmlreport.py @@ -1,3 +1,6 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt + """XML reporting for coverage.py""" import os @@ -5,9 +8,15 @@ import sys import time import xml.dom.minidom -from coverage import __url__, __version__ +from coverage import __url__, __version__, files from coverage.report import Reporter +DTD_URL = ( + 'https://raw.githubusercontent.com/cobertura/web/' + 'f0366e5e2cf18f111cbd61fc34ef720a6584ba02' + '/htdocs/xml/coverage-03.dtd' +) + def rate(hit, num): """Return the fraction of `hit`/`num`, as a string.""" @@ -20,10 +29,9 @@ def rate(hit, num): class XmlReporter(Reporter): """A reporter for writing Cobertura-style XML coverage results.""" - def __init__(self, coverage, config, file_locator): + def __init__(self, coverage, config): super(XmlReporter, self).__init__(coverage, config) - self.file_locator = file_locator self.source_paths = set() self.packages = {} self.xml_out = None @@ -42,11 +50,7 @@ class XmlReporter(Reporter): # 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" - ) - self.xml_out = impl.createDocument(None, "coverage", docType) + self.xml_out = impl.createDocument(None, "coverage", None) # Write header stuff. xcoverage = self.xml_out.documentElement @@ -55,6 +59,7 @@ class XmlReporter(Reporter): xcoverage.appendChild(self.xml_out.createComment( " Generated by coverage.py: %s " % __url__ )) + xcoverage.appendChild(self.xml_out.createComment(" Based on %s " % DTD_URL)) # Call xml_file for each file in the data. self.report_files(self.xml_file, morfs) @@ -122,15 +127,15 @@ class XmlReporter(Reporter): # Create the 'lines' and 'package' XML elements, which # are populated later. Note that a package == a directory. - filename = self.file_locator.relative_filename(fr.filename) + filename = files.relative_filename(fr.filename) filename = filename.replace("\\", "/") dirname = os.path.dirname(filename) or "." parts = dirname.split("/") dirname = "/".join(parts[:self.config.xml_package_depth]) package_name = dirname.replace("/", ".") - className = fr.name + className = fr.relative_filename() - self.source_paths.add(self.file_locator.relative_dir.rstrip('/')) + self.source_paths.add(files.relative_directory().rstrip('/')) package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0]) xclass = self.xml_out.createElement("class") @@ -145,6 +150,7 @@ class XmlReporter(Reporter): xclass.setAttribute("complexity", "0") branch_stats = analysis.branch_stats() + missing_branch_arcs = analysis.missing_branch_arcs() # For each statement, create an XML 'line' element. for line in sorted(analysis.statements): @@ -163,6 +169,9 @@ class XmlReporter(Reporter): "condition-coverage", "%d%% (%d/%d)" % (100*taken/total, taken, total) ) + if line in missing_branch_arcs: + annlines = ["exit" if b < 0 else str(b) for b in missing_branch_arcs[line]] + xline.setAttribute("missing-branches", ",".join(annlines)) xlines.appendChild(xline) class_lines = len(analysis.statements) |