diff options
-rw-r--r-- | CHANGES.txt | 20 | ||||
-rw-r--r-- | coverage/results.py | 21 | ||||
-rw-r--r-- | coverage/xmlreport.py | 18 | ||||
-rw-r--r-- | test/farm/html/gold_y_xml_branch/coverage.xml | 2 |
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"/>
|