Description
foo.py:
def doit(o, r):
try:
_doit(o, r)
except:
pass
def _doit(o, r):
try:
if r:
raise ValueError("hey")
except ValueError:
raise Exception("hi")
finally:
if o:
print("close")
return "boo"
doit(False, True)
doit(True, False)
When run with branch coverage (Python 3.8, if it matters), produces this output:
The two yellow lines are both right: those are branches that are not fully exercised, but the explanations in the annotations are wrong.
The annotation on line 14 says:
line 14 didn't jump to line 17, because the condition on line 14 was never false
This isn't true: the condition on line 14 was false at one point. Line 14 can go three places:
- line 15 (if the condition is true)
- exit the function (if the condition is false and an exception is being raised)
- line 17 (if the condition is false and an exception isn't being raised)
What's missing from the coverage is the third possibility, but the annotation doesn't make that clear.
The annotation on line 15 says:
line 15 didn't except from function '_doit', because the raise on line 12 wasn't executed
This isn't true: the raise on line 12 was executed. Line 15 will except from the function only if two conditions are met: the raise on line 12 is executed and the condition on line 14 is true. It's this combination that is missing, but the annotation doesn't make this clear.