diff options
Diffstat (limited to 'coverage/xmlreport.py')
-rw-r--r-- | coverage/xmlreport.py | 74 |
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) |