summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt20
-rw-r--r--coverage/results.py21
-rw-r--r--coverage/xmlreport.py18
-rw-r--r--test/farm/html/gold_y_xml_branch/coverage.xml2
4 files changed, 43 insertions, 18 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 62336f6b..2529ef27 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,21 +10,27 @@ Version 3.4b2
as 0% covered. This only happens if the --source option is specified, since
coverage.py needs guidance about where to look for source files.
-- Coverage percentages are now displayed uniformly across reporting methods. A
- percentage is only reported as 0% or 100% if they are truly 0 or 100, and
- are rounded otherwise. Fixes `issue 41` and issue 70`.
+- The XML report output now properly includes a percentage for branch coverage,
+ fixing `issue 65`_ and `issue 81`_.
+
+- Coverage percentages are now displayed uniformly across reporting methods.
+ Previously, different reports could round percentages differently. Also,
+ percentages are only reported as 0% or 100% if they are truly 0 or 100, and
+ are rounded otherwise. Fixes `issue 41`_ and `issue 70`_.
- The precision of reported coverage percentages can be set with the
``[report] precision`` config file setting. Default is still 0. Completes
- ``issue 16``.
+ `issue 16`_.
- Threads derived from ``threading.Thread`` with an overridden `run` method
would report no coverage for the `run` method. This is now fixed, closing
- ``issue 85``.
+ `issue 85`_.
-.. _issue 70: http://bitbucket.org/ned/coveragepy/issue/70/text-report-and-html-report-disagree-on-coverage
-.. _issue 41: http://bitbucket.org/ned/coveragepy/issue/41/report-says-100-when-it-isnt-quite-there
.. _issue 16: http://bitbucket.org/ned/coveragepy/issue/16/allow-configuration-of-accuracy-of-percentage-totals
+.. _issue 41: http://bitbucket.org/ned/coveragepy/issue/41/report-says-100-when-it-isnt-quite-there
+.. _issue 65: http://bitbucket.org/ned/coveragepy/issue/65/branch-option-not-reported-in-cobertura
+.. _issue 70: http://bitbucket.org/ned/coveragepy/issue/70/text-report-and-html-report-disagree-on-coverage
+.. _issue 81: http://bitbucket.org/ned/coveragepy/issue/81/xml-report-does-not-have-condition-coverage-attribute-for-lines-with-a
.. _issue 85: http://bitbucket.org/ned/coveragepy/issue/85/threadrun-isnt-measured
diff --git a/coverage/results.py b/coverage/results.py
index e6e39429..85071fe3 100644
--- a/coverage/results.py
+++ b/coverage/results.py
@@ -94,7 +94,7 @@ class Analysis(object):
return sorted(unpredicted)
def branch_lines(self):
- """Returns lines that have more than one exit."""
+ """Returns a list of line numbers that have more than one exit."""
exit_counts = self.parser.exit_counts()
return [l1 for l1,count in exit_counts.items() if count > 1]
@@ -119,6 +119,25 @@ class Analysis(object):
mba[l1].append(l2)
return mba
+ def branch_stats(self):
+ """Get stats about branches.
+
+ Returns a dict mapping line numbers to a tuple:
+ (total_exits, taken_exits).
+ """
+
+ exit_counts = self.parser.exit_counts()
+ missing_arcs = self.missing_branch_arcs()
+ stats = {}
+ for lnum in self.branch_lines():
+ exits = exit_counts[lnum]
+ try:
+ missing = len(missing_arcs[lnum])
+ except KeyError:
+ missing = 0
+ stats[lnum] = (exits, exits - missing)
+ return stats
+
class Numbers(object):
"""The numerical results of measuring coverage.
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py
index 7a6e5147..51405be6 100644
--- a/coverage/xmlreport.py
+++ b/coverage/xmlreport.py
@@ -9,7 +9,7 @@ from coverage.report import Reporter
def rate(hit, num):
"""Return the fraction of `hit`/`num`."""
- return hit / (num or 1.0)
+ return float(hit) / (num or 1.0)
class XmlReporter(Reporter):
@@ -105,7 +105,7 @@ class XmlReporter(Reporter):
xclass.setAttribute("filename", cu.name + ext)
xclass.setAttribute("complexity", "0.0")
- branch_lines = analysis.branch_lines()
+ branch_stats = analysis.branch_stats()
# For each statement, create an XML 'line' element.
for line in analysis.statements:
@@ -117,20 +117,20 @@ class XmlReporter(Reporter):
xline.setAttribute("hits", str(int(not line 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_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_branches = sum([t for t,k in branch_stats.values()])
+ missing_branches = sum([t-k for t,k in branch_stats.values()])
class_branch_hits = class_branches - missing_branches
else:
class_branches = 0.0
diff --git a/test/farm/html/gold_y_xml_branch/coverage.xml b/test/farm/html/gold_y_xml_branch/coverage.xml
index 9a3efca2..34e02dc7 100644
--- a/test/farm/html/gold_y_xml_branch/coverage.xml
+++ b/test/farm/html/gold_y_xml_branch/coverage.xml
@@ -10,7 +10,7 @@
<methods/>
<lines>
<line hits="1" number="3"/>
- <line branch="true" hits="1" number="4"/>
+ <line branch="true" condition-coverage="50% (1/2)" hits="1" number="4"/>
<line hits="1" number="5"/>
<line hits="0" number="7"/>
<line hits="1" number="9"/>