[TIP] [coverage.py] concept question about branch coverage, statement coverage, and percent coverage

Ned Batchelder ned at nedbatchelder.com
Sat Apr 4 14:31:45 PDT 2020


On 3/31/20 8:19 PM, Enji Cooper wrote:
> Hi,
> 	I have a general question about a few of the tests that come packaged with coverage.py, related to “line coverage”, “statement coverage”, and “branch coverage”.
> 	The code snippet from BasicCoverageTest.test_simple is as follows:
>
> “””\
>              a = 1
>              b = 2
>              
>              c = 4
>              # Nothing here
>              d = 6
> “””
> 	Per the above example, lines 1, 2, 4, and 6 are executed, but nothing else. The line coverage is 4/4 => 100% and the number of statements executed is also 4/4, resulting in 100% line/statement coverage. There aren’t any branches in the above code, so I would put down something like “N/A”.
> 	The asserted report (abbreviated) is as follows:
>
> 	# The fields in `report` translate to "Statements, Miss, Branch, Partial Branches, Cover"
> 	lines=[1,2,4,6], report="4 0 0 0 100%
>
> 	The test asserts that lines {1, 2, 4, 6} are executed, which is a total of 4/4 lines/statements executed, no statements missed, no branches taken, no partial branches, resulting in 100% line/statement coverage. Seems legit (the expected results match my understanding).
> 	If my above understanding is correct, let’s continue on to the next example.
> 	The code snippet from CompoundStatementTest.test_elif is as follows:
>
> """\
>              a = 1; b = 2; c = 3;
>              if a == 1:
>                  x = 3
>              elif b == 2:
>                  y = 5
>              else:
>                  z = 7
>              assert x == 3
> “””
>
> 	In this case, there are 8 total lines, 11 statements (line 1 contains 3 statements) and 4 possible branches (`if a == 1`, `elif b == 2`, `else:` and `assert x == 3`). Since a=1, lines 1-3 and 8 are executed, but none of the other lines are executed. 6 of the 11 statements are executed, and only 2 of the branch statements (the first being `if a == 1`, the second being `assert x == 3`) are executed. If my understand was correct, this should result in 50% line coverage, 54.55% statement coverage, and 50% branch coverage. This however, isn’t what the test expects:
>
> 	# The fields in `report` translate to "Statements, Miss, Branch, Partial Branches, Cover, Missing"
> 	lines=[1,2,3,4,5,7,8], missing="4-7", report="7 3 4 1 45% 2->4, 4-7”
>
> 	I agree on the `lines` and `missing` value, but the rest of the values seem askew:
>
> 	* There are 10 statements, not 7 statements.
> 	* There are 4 missed statements/lines, not 3 statements/lines.
> 	* There are 4 total branches (I agree on that part at least).
> 	* There is 1 partial branch taken (err… this seems odd — which branch is that?).
> 	* The overall statement/line coverage is assumed to be 45% (how is that calculated?).
> 	* The missing lines are 2->4 (a jump statement), and 4-7.
>
> 	Could someone please explain why these expected values are as noted above?

There are only 7 statements, not 10, for two reasons: first, "else:" 
doesn't result in any compiled code. Execution never jumps to "else", it 
jumps directly to the statement after else.  Second, Python won't report 
on multiple statements in a line, so "a = 1; b = 2; c = 3;" is counted 
as one statement.

There are three missed statements because "else" is not a statement.

The partial branch is "if a == 1", because it was only ever true, never 
false.

The coverage.py FAQ 
(https://coverage.readthedocs.io/en/latest/faq.html#q-how-is-the-total-percentage-calculated) 
explains how the percentage is calculated: (statements - 
missed_statements + branch_exits - missed_branch_exits) / (statements + 
branch_exits)

In this case, that works out to (7 - 3 + 4 - 3) / (7 + 4) = 45%

As the FAQ notes, the coverage.py reports don't show the number of 
branch exits and missed branch exits.  They show the number of branches 
and number of total branches, so it's a bit hard to reconstruct the 
calculation from the reports.

--Ned.


> Thank you,
> -Enji
>
> 1. https://www.cs.odu.edu/~cs252/Book/stmtcov.html
> 2. https://www.cs.odu.edu/~cs252/Book/branchcov.html
> 3. https://www.froglogic.com/coco/statement-coverage/
> _______________________________________________
> testing-in-python mailing list
> testing-in-python at lists.idyll.org
> http://lists.idyll.org/listinfo/testing-in-python



More information about the testing-in-python mailing list