diff options
-rw-r--r-- | TODO.txt | 1 | ||||
-rw-r--r-- | doc/branch.rst | 92 |
2 files changed, 79 insertions, 14 deletions
@@ -13,6 +13,7 @@ Coverage TODO (see top of test_cogapp for examples)
- Maybe turning off yellow lines should make those lines green?
- A missing branch to leave the function shows an annotation of -1.
+- XML report needs to get branch information.
* Speed
diff --git a/doc/branch.rst b/doc/branch.rst index 5419d1c1..9b03861d 100644 --- a/doc/branch.rst +++ b/doc/branch.rst @@ -1,24 +1,88 @@ -Coverage.py now supports branch coverage +.. _branch: -- How to use it. +=========================== +Branch coverage measurement +=========================== -- Reporting +Coverage.py now supports branch coverage measurement. Where a line in your +program could jump to more than one next line, coverage.py tracks which of +those destinations are actually visited, and flags lines that haven't visited +all of their possible destinations. -- How it works +For example:: -- Odd cases - - - yellow-pink syndrome: + def my_partial_fn(x): # line 1 + if x: # 2 + y = 10 # 3 + return y # 4 + + my_partial_fn(1) - Y if never_true: - P never_executed() +In this code, the if on line 2 could branch to either line 3 or line 4. +Statement coverage would show all lines of the function as executed. But the +if is always true, so line 2 never jumps to line 4. In this code, that +path would cause an error. + +Branch coverage would flag this code as not fully covered because of the +missing jump from line 2 to line 4. + + +How to measure branch coverage +------------------------------ + +To measure branch coverage, run coverage.py with the --branch flag:: + + coverage run --branch myprog.py - - while True is marked as yellow +When you report on the results with "coverage report" or "coverage html", the +percentage of branch possibilities taken will be included in the percentage +covered total for each file. The coverage percentage for a file is the +actual executions divided by the execution opportunities. Each line in the +file is an execution opportunity, as is each branch destination. + +Currently, only HTML reports give information about which lines had missing +branches. Lines that were missing some branches are shown in yellow, with an +annotation at the far right of branch destination line numbers that were not +exercised. + + +How it works +------------ - - except ValueError will be marked as yellow if you never see a different exception. +When measuring branches, coverage.py collects pairs of line numbers, a source +and destination for each transition from one line to another. Static analysis +of the compiled bytecode provides a list of possible transitions. Comparing +the measured to the possible indicates missing branches. + +The idea of tracking how lines follow each other was from C. Titus Brown. +Thanks, Titus! + + +Problems +-------- + +Some Python constructs are difficult to measure properly. For example, an +infinite loop will be marked as partially executed:: + + while True: # line 1 + if some_condition(): # 2 + break + body_of_loop() # 4 -- Exceptions? + keep_working() # 6 + +Because the loop never terminates naturally (jumping from line 1 to 6), +coverage.py thinks the branch is partially executed. + +Currently, if you exclude code from coverage testing, a branch into that code +will still be considered executable, and may result in the branch being +flagged. + - - What should we do with the info about unpredicted arcs? +Other work +---------- -- Excluding. Does it work? +One interesting side effect of tracking line transitions: we know where some +exceptions happened because a transition happens that wasn't predicted by the +static analysis. Currently, I'm not doing anything with this information. +Any ideas? |