diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2009-09-25 07:52:21 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2009-09-25 07:52:21 -0400 |
commit | 97bdac70cc42ca7cb87cfbb3edf2f5ea1b9fa767 (patch) | |
tree | d4cf8a9c74931ec0e5eaa05ef17e5ee2fdb86070 /coverage/xmlreport.py | |
parent | 98f9e829485eeba4fbe51d98cebf6c7050ade482 (diff) | |
download | python-coveragepy-97bdac70cc42ca7cb87cfbb3edf2f5ea1b9fa767.tar.gz |
Clean up the XML code, use common reporting infrastructure, add a Generator comment, don't output packages that don't really exist.
Diffstat (limited to 'coverage/xmlreport.py')
-rw-r--r-- | coverage/xmlreport.py | 145 |
1 files changed, 74 insertions, 71 deletions
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py index 8d5e4dd..dbec7e9 100644 --- a/coverage/xmlreport.py +++ b/coverage/xmlreport.py @@ -3,7 +3,8 @@ import os, sys import xml.dom.minidom -from coverage.backward import sorted +from coverage import __version__ +from coverage.backward import sorted # pylint: disable-msg=W0622 from coverage.report import Reporter @@ -12,6 +13,9 @@ class XmlReporter(Reporter): def __init__(self, coverage, ignore_errors=False): super(XmlReporter, self).__init__(coverage, ignore_errors) + + self.packages = None + self.xml_out = None def report(self, morfs, omit_prefixes=None, outfile=None): """Generate a Cobertura-compatible XML report for `morfs`. @@ -28,88 +32,87 @@ class XmlReporter(Reporter): 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 + "http://cobertura.sourceforge.net/xml/coverage-03.dtd" + ) + self.xml_out = impl.createDocument(None, "coverage", docType) + root = self.xml_out.documentElement - packageXml = doc.createElement("packages") + root.appendChild(self.xml_out.createComment( + " Generated by coverage.py %s: " + "http://nedbatchelder.com/code/coverage " % __version__ + )) + packageXml = self.xml_out.createElement("packages") root.appendChild(packageXml) - packages = {} + self.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. - dirname, fname = os.path.split(cu.name) - dirname = dirname or '.' - package = packages.setdefault( - dirname, [ 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.filename) - c.setAttribute("complexity", "0.0") - - try: - statements, _, missing, _ = 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. - l.setAttribute("hits", str(int(not line in 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") - 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. - line_rate = class_hits / (class_lines or 1.0) - branch_rate = class_branch_hits / (class_branches or 1.0) - c.setAttribute("line-rate", str(line_rate)) - c.setAttribute("branch-rate", str(branch_rate)) - 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 - + + self.report_files(self.xml_file, morfs, omit_prefixes=omit_prefixes) + # 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] + for packageName, packageData in self.packages.items(): + package = self.xml_out.createElement("package") packageXml.appendChild(package) - classes = doc.createElement("classes") + classes = self.xml_out.createElement("classes") package.appendChild(classes) - for className in sorted(packageData[1].keys()): - classes.appendChild(packageData[1][className]) + for className in sorted(packageData[0].keys()): + classes.appendChild(packageData[0][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("line-rate", str(packageData[1]/(packageData[2] or 1.0))) + package.setAttribute("branch-rate", str(packageData[3]/(packageData[4] or 1.0))) package.setAttribute("complexity", "0.0") # Use the DOM to write the output file. - outfile.write(doc.toprettyxml()) + outfile.write(self.xml_out.toprettyxml()) + + def xml_file(self, cu, statements, excluded, missing): + """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) + dirname = dirname or '.' + package = self.packages.setdefault(dirname, [ {}, 0, 0, 0, 0 ]) + c = self.xml_out.createElement("class") + lines = self.xml_out.createElement("lines") + c.appendChild(lines) + className = fname.replace('.', '_') + c.setAttribute("name", className) + c.setAttribute("filename", cu.filename) + c.setAttribute("complexity", "0.0") + + # For each statement, create an XML 'line' element. + for line in statements: + l = self.xml_out.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. + l.setAttribute("hits", str(int(not line in 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") + 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. + line_rate = class_hits / (class_lines or 1.0) + branch_rate = class_branch_hits / (class_branches or 1.0) + c.setAttribute("line-rate", str(line_rate)) + c.setAttribute("branch-rate", str(branch_rate)) + package[0][className] = c + package[1] += class_hits + package[2] += class_lines + package[3] += class_branch_hits + package[4] += class_branches |