summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2009-11-08 17:38:51 -0500
committerNed Batchelder <ned@nedbatchelder.com>2009-11-08 17:38:51 -0500
commit5ed5253d89664d675566b8ea36677a75158ede4b (patch)
tree4b26b6f73685f1a5755b30bf9ac2ea9fb0f0a304
parent715ceff602f744cf3ddd3e60bd65260250b8163f (diff)
downloadpython-coveragepy-git-5ed5253d89664d675566b8ea36677a75158ede4b.tar.gz
Dict literals shouldn't count as many different exits.
-rw-r--r--CHANGES.txt4
-rw-r--r--TODO.txt2
-rw-r--r--coverage/parser.py31
-rw-r--r--coverage/results.py18
-rw-r--r--test/test_arcs.py18
5 files changed, 51 insertions, 22 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index a7c5b1b0..ff1ee52e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -5,11 +5,15 @@ Change history for Coverage.py
Next version
------------
+- Branch coverage.
+
- The tracer code has changed, it's a few percent faster.
- Some exceptions reported by the command line interface have been cleaned up
so that tracebacks inside coverage.py aren't shown. Fixes `issue 23`_
+- XML reporting has file paths that let Cobertura find the source code.
+
.. _issue 23: http://bitbucket.org/ned/coveragepy/issue/23
diff --git a/TODO.txt b/TODO.txt
index bdedd44f..e730a2dd 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -36,7 +36,7 @@ x Tricky swapping of collector like figleaf, pycov, et al. (Don't need to do
* Power
-- Branch coverage
++ Branch coverage
Titus' idea:
1: if a:
2: b = 2
diff --git a/coverage/parser.py b/coverage/parser.py
index 7721d8db..4890aa6f 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -186,11 +186,27 @@ class CodeParser(object):
normalized to the first line of multiline statements.
"""
- all_arcs = self.byte_parser._all_arcs()
- m2fl = self.first_line
- all_arcs = [(m2fl(l1), m2fl(l2)) for (l1,l2) in all_arcs]
+ all_arcs = []
+ for l1, l2 in self.byte_parser._all_arcs():
+ fl1 = self.first_line(l1)
+ fl2 = self.first_line(l2)
+ if fl1 != fl2:
+ all_arcs.append((fl1, fl2))
return sorted(all_arcs)
+ def exit_counts(self):
+ """Return a dict mapping line numbers to number of exits from that line."""
+ exit_counts = {}
+ for l1,l2 in self.arcs():
+ if l1 == -1:
+ continue
+ if l1 not in exit_counts:
+ exit_counts[l1] = 0
+ exit_counts[l1] += 1
+
+ return exit_counts
+
+
## Opcodes that guide the ByteParser.
def _opcode(name):
@@ -592,17 +608,22 @@ class AdHocMain(object):
else:
arc_width, arc_chars = 0, {}
+ exit_counts = cp.exit_counts()
+
for i, ltext in enumerate(cp.lines):
lineno = i+1
- m0 = m1 = m2 = a = ' '
+ m0 = m1 = m2 = m3 = a = ' '
if lineno in cp.statement_starts:
m0 = '-'
if lineno in cp.docstrings:
m1 = '"'
if lineno in cp.excluded:
m2 = 'x'
+ exits = exit_counts.get(lineno, 0)
+ if exits > 1:
+ m3 = str(exits)
a = arc_chars.get(lineno, '').ljust(arc_width)
- print("%4d %s%s%s%s %s" % (lineno, m0, m1, m2, a, ltext))
+ print("%4d %s%s%s%s%s %s" % (lineno, m0, m1, m2, m3, a, ltext))
def arc_ascii_art(self, arcs):
"""Draw arcs as ascii art.
diff --git a/coverage/results.py b/coverage/results.py
index 59cc1fa9..6f4117a8 100644
--- a/coverage/results.py
+++ b/coverage/results.py
@@ -96,25 +96,11 @@ class Analysis(object):
def branch_lines(self):
"""Returns lines that have more than one exit."""
- exit_counts = {}
- for l1,l2 in self.arc_possibilities():
- if l1 == -1:
- continue
- if l1 not in exit_counts:
- exit_counts[l1] = 0
- exit_counts[l1] += 1
-
+ exit_counts = self.parser.exit_counts()
return [l1 for l1,count in exit_counts.items() if count > 1]
def total_branches(self):
- exit_counts = {}
- for l1,l2 in self.arc_possibilities():
- if l1 == -1:
- continue
- if l1 not in exit_counts:
- exit_counts[l1] = 0
- exit_counts[l1] += 1
-
+ exit_counts = self.parser.exit_counts()
return sum([count for count in exit_counts.values() if count > 1])
def missing_branch_arcs(self):
diff --git a/test/test_arcs.py b/test/test_arcs.py
index 462ff2fc..00567ac6 100644
--- a/test/test_arcs.py
+++ b/test/test_arcs.py
@@ -394,3 +394,21 @@ class ExceptionArcTest(CoverageTest):
""",
arcz=".1 12 .3 3. 24 45 56 67 7B 89 9B BC C.",
arcz_missing="67 7B", arcz_unpredicted="68")
+
+
+class MiscArcTest(CoverageTest):
+ """Miscellaneous arc-measuring tests."""
+
+ def test_dict_literal(self):
+ self.check_coverage("""\
+ d = {
+ 'a': 2,
+ 'b': 3,
+ 'c': {
+ 'd': 5,
+ 'e': 6,
+ }
+ }
+ assert d
+ """,
+ arcz=".1 19 9.")