DebugClients/Python3/coverage/xmlreport.py

branch
Py2 comp.
changeset 3495
fac17a82b431
parent 29
391dc0bc4ae5
child 4489
d0d6e4ad31bd
--- a/DebugClients/Python3/coverage/xmlreport.py	Fri Apr 04 22:57:07 2014 +0200
+++ b/DebugClients/Python3/coverage/xmlreport.py	Thu Apr 10 23:02:20 2014 +0200
@@ -4,29 +4,30 @@
 import xml.dom.minidom
 
 from . import __url__, __version__
-from .backward import sorted            # pylint: disable-msg=W0622
+from .backward import sorted, rpartition    # pylint: disable=W0622
 from .report import Reporter
 
 def rate(hit, num):
-    """Return the fraction of `hit`/`num`."""
-    return hit / (num or 1.0)
+    """Return the fraction of `hit`/`num`, as a string."""
+    return "%.4g" % (float(hit) / (num or 1.0))
 
 
 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 __init__(self, coverage, config):
+        super(XmlReporter, self).__init__(coverage, config)
 
         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, 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.
+
+        `outfile` is a file object to write the XML to.
 
         """
         # Initial setup.
@@ -52,44 +53,54 @@
 
         # Call xml_file for each file in the data.
         self.packages = {}
-        self.report_files(self.xml_file, morfs, omit_prefixes=omit_prefixes)
+        self.report_files(self.xml_file, morfs)
 
         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():
+        for pkg_name in sorted(self.packages.keys()):
+            pkg_data = self.packages[pkg_name]
             class_elts, lhits, lnum, bhits, bnum = pkg_data
             xpackage = self.xml_out.createElement("package")
             xpackages.appendChild(xpackage)
             xclasses = self.xml_out.createElement("classes")
             xpackage.appendChild(xclasses)
-            for className in sorted(class_elts.keys()):
-                xclasses.appendChild(class_elts[className])
+            for class_name in sorted(class_elts.keys()):
+                xclasses.appendChild(class_elts[class_name])
             xpackage.setAttribute("name", pkg_name.replace(os.sep, '.'))
-            xpackage.setAttribute("line-rate", str(rate(lhits, lnum)))
-            xpackage.setAttribute("branch-rate", str(rate(bhits, bnum)))
-            xpackage.setAttribute("complexity", "0.0")
+            xpackage.setAttribute("line-rate", rate(lhits, lnum))
+            xpackage.setAttribute("branch-rate", rate(bhits, bnum))
+            xpackage.setAttribute("complexity", "0")
 
             lnum_tot += lnum
             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)))
+        xcoverage.setAttribute("line-rate", rate(lhits_tot, lnum_tot))
+        xcoverage.setAttribute("branch-rate", rate(bhits_tot, bnum_tot))
 
         # Use the DOM to write the output file.
         outfile.write(self.xml_out.toprettyxml())
 
+        # Return the total percentage.
+        denom = lnum_tot + bnum_tot
+        if denom == 0:
+            pct = 0.0
+        else:
+            pct = 100.0 * (lhits_tot + bhits_tot) / denom
+        return pct
+
     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)
-        dirname = dirname or '.'
-        package = self.packages.setdefault(dirname, [ {}, 0, 0, 0, 0 ])
+        package_name = rpartition(cu.name, ".")[0]
+        className = cu.name
+
+        package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0])
 
         xclass = self.xml_out.createElement("class")
 
@@ -97,50 +108,48 @@
 
         xlines = self.xml_out.createElement("lines")
         xclass.appendChild(xlines)
-        className = fname.replace('.', '_')
+
         xclass.setAttribute("name", className)
-        ext = os.path.splitext(cu.filename)[1]
-        xclass.setAttribute("filename", cu.name + ext)
-        xclass.setAttribute("complexity", "0.0")
+        filename = cu.file_locator.relative_filename(cu.filename)
+        xclass.setAttribute("filename", filename.replace("\\", "/"))
+        xclass.setAttribute("complexity", "0")
 
-        branch_lines = analysis.branch_lines()
+        branch_stats = analysis.branch_stats()
 
         # For each statement, create an XML 'line' element.
-        for line in analysis.statements:
+        for line in sorted(analysis.statements):
             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.
-            xline.setAttribute("hits", str(int(not line in analysis.missing)))
+            xline.setAttribute("hits", str(int(line not in analysis.missing)))
 
             if self.arcs:
-                if line in branch_lines:
+                if line in branch_stats:
+                    total, taken = branch_stats[line]
                     xline.setAttribute("branch", "true")
+                    xline.setAttribute("condition-coverage",
+                        "%d%% (%d/%d)" % (100*taken/total, taken, total)
+                        )
             xlines.appendChild(xline)
 
-        class_lines = 1.0 * len(analysis.statements)
+        class_lines = len(analysis.statements)
         class_hits = class_lines - len(analysis.missing)
 
         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
+            class_branches = sum([t for t,k in branch_stats.values()])
+            missing_branches = sum([t-k for t,k in branch_stats.values()])
+            class_br_hits = class_branches - missing_branches
         else:
             class_branches = 0.0
-            class_branch_hits = 0.0
+            class_br_hits = 0.0
 
         # Finalize the statistics that are collected in the XML DOM.
-        line_rate = rate(class_hits, class_lines)
-        branch_rate = rate(class_branch_hits, class_branches)
-        xclass.setAttribute("line-rate", str(line_rate))
-        xclass.setAttribute("branch-rate", str(branch_rate))
+        xclass.setAttribute("line-rate", rate(class_hits, class_lines))
+        xclass.setAttribute("branch-rate", rate(class_br_hits, class_branches))
         package[0][className] = xclass
         package[1] += class_hits
         package[2] += class_lines
-        package[3] += class_branch_hits
+        package[3] += class_br_hits
         package[4] += class_branches

eric ide

mercurial