diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2018-12-25 07:51:02 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2018-12-25 07:51:02 -0500 |
commit | 31a42af7739f55033f122b28eb4beb0bb4ffdafd (patch) | |
tree | a91c47c24f30f053e4e68e266ff83db19d1b52f2 | |
parent | dcb07762bfc91dec3782096ab6dae995e7c6631a (diff) | |
download | python-coveragepy-git-31a42af7739f55033f122b28eb4beb0bb4ffdafd.tar.gz |
Sort the text missing results by line number, not kind
-rw-r--r-- | CHANGES.rst | 4 | ||||
-rw-r--r-- | coverage/results.py | 78 | ||||
-rw-r--r-- | coverage/summary.py | 9 | ||||
-rw-r--r-- | tests/test_coverage.py | 10 | ||||
-rw-r--r-- | tests/test_results.py | 24 | ||||
-rw-r--r-- | tests/test_summary.py | 2 |
6 files changed, 77 insertions, 50 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index b00d0f2b..ab49f22a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,6 +19,10 @@ Unreleased - ``fail_under`` values more than 100 are reported as errors. Thanks to Mike Fiedler for closing `issue 746`_. +- The "missing" values in the text output are now sorted by line number, so + that missing branches are reported near the other lines they affect. The + values used to show all missing lines, and then all missing branches. + .. _issue 746: https://github.com/nedbat/coveragepy/issues/746 diff --git a/coverage/results.py b/coverage/results.py index f7e0ae56..529899de 100644 --- a/coverage/results.py +++ b/coverage/results.py @@ -49,13 +49,20 @@ class Analysis(object): n_missing_branches=n_missing_branches, ) - def missing_formatted(self): + def missing_formatted(self, branches=False): """The missing line numbers, formatted nicely. Returns a string like "1-2, 5-11, 13-14". + If `branches` is true, includes the missing branch arcs also. + """ - return format_lines(self.statements, self.missing) + if branches and self.has_arcs(): + arcs = iitems(self.missing_branch_arcs()) + else: + arcs = None + + return format_lines(self.statements, self.missing, arcs=arcs) def has_arcs(self): """Were arcs measured in this result?""" @@ -82,24 +89,6 @@ class Analysis(object): ) return sorted(missing) - def arcs_missing_formatted(self): - """The missing branch arcs, formatted nicely. - - Returns a string like "1->2, 1->3, 16->20". Omits any mention of - branches from missing lines, so if line 17 is missing, then 17->18 - won't be included. - - """ - arcs = self.missing_branch_arcs() - missing = self.missing - line_exits = sorted(iitems(arcs)) - pairs = [] - for line, exits in line_exits: - for ex in sorted(exits): - if line not in missing: - pairs.append("%d->%s" % (line, (ex if ex > 0 else "exit"))) - return ', '.join(pairs) - def arcs_unpredicted(self): """Returns a sorted list of the executed arcs missing from the code.""" possible = self.arc_possibilities() @@ -272,21 +261,8 @@ class Numbers(SimpleReprMixin): return NotImplemented -def format_lines(statements, lines): - """Nicely format a list of line numbers. - - Format a list of line numbers for printing by coalescing groups of lines as - long as the lines represent consecutive statements. This will coalesce - even if there are gaps between statements. - - For example, if `statements` is [1,2,3,4,5,10,11,12,13,14] and - `lines` is [1,2,5,10,11,13,14] then the result will be "1-2, 5-11, 13-14". - - Both `lines` and `statements` can be any iterable. All of the elements of - `lines` must be in `statements`, and all of the values must be positive - integers. - - """ +def _line_ranges(statements, lines): + """Produce a list of ranges for `format_lines`.""" statements = sorted(statements) lines = sorted(lines) @@ -306,7 +282,37 @@ def format_lines(statements, lines): start = None if start: pairs.append((start, end)) - ret = ', '.join(map(nice_pair, pairs)) + return pairs + + +def format_lines(statements, lines, arcs=None): + """Nicely format a list of line numbers. + + Format a list of line numbers for printing by coalescing groups of lines as + long as the lines represent consecutive statements. This will coalesce + even if there are gaps between statements. + + For example, if `statements` is [1,2,3,4,5,10,11,12,13,14] and + `lines` is [1,2,5,10,11,13,14] then the result will be "1-2, 5-11, 13-14". + + Both `lines` and `statements` can be any iterable. All of the elements of + `lines` must be in `statements`, and all of the values must be positive + integers. + + If `arcs` is provided, they are (start,[end,end,end]) pairs that will be + included in the output as long as start isn't in `lines`. + + """ + line_items = [(pair[0], 0, nice_pair(pair)) for pair in _line_ranges(statements, lines)] + if arcs: + line_exits = sorted(arcs) + for line, exits in line_exits: + for ex in sorted(exits): + if line not in lines: + dest = (ex if ex > 0 else "exit") + line_items.append((line, 1, "%d->%s" % (line, dest))) + + ret = ', '.join(t[-1] for t in sorted(line_items)) return ret diff --git a/coverage/summary.py b/coverage/summary.py index 95afbcf0..e79592b9 100644 --- a/coverage/summary.py +++ b/coverage/summary.py @@ -110,14 +110,7 @@ class SummaryReporter(Reporter): args += (nums.n_branches, nums.n_partial_branches) args += (nums.pc_covered_str,) if self.config.show_missing: - missing_fmtd = analysis.missing_formatted() - if self.branches: - branches_fmtd = analysis.arcs_missing_formatted() - if branches_fmtd: - if missing_fmtd: - missing_fmtd += ", " - missing_fmtd += branches_fmtd - args += (missing_fmtd,) + args += (analysis.missing_formatted(branches=True),) text = fmt_coverage % args # Add numeric percent coverage so that sorting makes sense. args += (nums.pc_covered,) diff --git a/tests/test_coverage.py b/tests/test_coverage.py index 947c5f1e..1b23f408 100644 --- a/tests/test_coverage.py +++ b/tests/test_coverage.py @@ -677,7 +677,7 @@ class CompoundStatementTest(CoverageTest): z = 7 assert x == 3 """, - [1,2,3,4,5,7,8], "4-7", report="7 3 4 1 45% 4-7, 2->4", + [1,2,3,4,5,7,8], "4-7", report="7 3 4 1 45% 2->4, 4-7", ) self.check_coverage("""\ a = 1; b = 2; c = 3; @@ -689,7 +689,7 @@ class CompoundStatementTest(CoverageTest): z = 7 assert y == 5 """, - [1,2,3,4,5,7,8], "3, 7", report="7 2 4 2 64% 3, 7, 2->3, 4->7", + [1,2,3,4,5,7,8], "3, 7", report="7 2 4 2 64% 2->3, 3, 4->7, 7", ) self.check_coverage("""\ a = 1; b = 2; c = 3; @@ -701,7 +701,7 @@ class CompoundStatementTest(CoverageTest): z = 7 assert z == 7 """, - [1,2,3,4,5,7,8], "3, 5", report="7 2 4 2 64% 3, 5, 2->3, 4->5", + [1,2,3,4,5,7,8], "3, 5", report="7 2 4 2 64% 2->3, 3, 4->5, 5", ) def test_elif_no_else(self): @@ -713,7 +713,7 @@ class CompoundStatementTest(CoverageTest): y = 5 assert x == 3 """, - [1,2,3,4,5,6], "4-5", report="6 2 4 1 50% 4-5, 2->4", + [1,2,3,4,5,6], "4-5", report="6 2 4 1 50% 2->4, 4-5", ) self.check_coverage("""\ a = 1; b = 2; c = 3; @@ -723,7 +723,7 @@ class CompoundStatementTest(CoverageTest): y = 5 assert y == 5 """, - [1,2,3,4,5,6], "3", report="6 1 4 2 70% 3, 2->3, 4->6", + [1,2,3,4,5,6], "3", report="6 1 4 2 70% 2->3, 3, 4->6", ) def test_elif_bizarre(self): diff --git a/tests/test_results.py b/tests/test_results.py index 8acbcaec..41494e66 100644 --- a/tests/test_results.py +++ b/tests/test_results.py @@ -124,3 +124,27 @@ def test_should_fail_under_invalid_value(): ]) def test_format_lines(statements, lines, result): assert format_lines(statements, lines) == result + + +@pytest.mark.parametrize("statements, lines, arcs, result", [ + ( + set([1,2,3,4,5,10,11,12,13,14]), + set([1,2,5,10,11,13,14]), + (), + "1-2, 5-11, 13-14" + ), + ( + [1,2,3,4,5,10,11,12,13,14,98,99], + [1,2,5,10,11,13,14,99], + [(3, [4]), (98, [100, -1])], + "1-2, 3->4, 5-11, 13-14, 98->100, 98->exit, 99" + ), + ( + [1,2,3,4,98,99,100,101,102,103,104], + [1,2,99,102,103,104], + [(3, [4]), (104, [-1])], + "1-2, 3->4, 99, 102-104" + ), +]) +def test_format_lines_with_arcs(statements, lines, arcs, result): + assert format_lines(statements, lines, arcs) == result diff --git a/tests/test_summary.py b/tests/test_summary.py index 60a96e64..8dd56e64 100644 --- a/tests/test_summary.py +++ b/tests/test_summary.py @@ -263,7 +263,7 @@ class SummaryTest(UsingModulesMixin, CoverageTest): 'Name Stmts Miss Branch BrPart Cover Missing', '---------------------------------------------------------', 'main.py 1 0 0 0 100%', - 'mybranch.py 10 2 8 3 61% 7-8, 2->4, 4->6, 6->7', + 'mybranch.py 10 2 8 3 61% 2->4, 4->6, 6->7, 7-8', '---------------------------------------------------------', 'TOTAL 11 2 8 3 63%', ] |