summaryrefslogtreecommitdiff
path: root/doc/branches.py
blob: 1fa705f04ac00687d9a00d71e67c383c6ab23c9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# Demonstrate some issues with coverage.py branch testing.

def my_function(x):
    """This isn't real code, just snippets..."""
    
    # An infinite loop is structurally still a branch: it can next execute the
    # first line of the loop, or the first line after the loop.  But
    # "while True" will never jump to the line after the loop, so the line
    # is shown as a partial branch:

    i = 0    
    while True:
        print "In while True"
        if i > 0:
            break
        i += 1
    print "Left the True loop"
    
    # Notice that "while 1" also has this problem.  Even though the compiler
    # knows there's no computation at the top of the loop, it's still expressed
    # in byte code as a branch with two possibilities.
    
    i = 0
    while 1:
        print "In while 1"
        if i > 0:
            break
        i += 1
    print "Left the 1 loop"
    
    # Coverage.py lets the developer exclude lines that he knows will not be
    # executed.  So far, the branch coverage doesn't use all that information
    # when deciding which lines are partially executed.
    #
    # Here, even though the else line is explicitly marked as never executed,
    # the if line complains that it never branched to the else:
    
    if x < 1000:
        # This branch is always taken
        print "x is reasonable"
    else:   # pragma: nocover
        print "this never happens"

    # try-except structures are complex branches.  An except clause with a
    # type is a three-way branch: there could be no exception, there could be
    # a matching exception, and there could be a non-matching exception.
    #
    # Here we run the code twice: once with no exception, and once with a
    # matching exception.  The "except" line is marked as partial because we
    # never executed its third case: a non-matching exception.
    
    for y in (1, 2):
        try:
            if y % 2:
                raise ValueError("y is odd!")
        except ValueError:
            print "y must have been odd"
        print "done with y"
    print "done with 1, 2"
    
    # Another except clause, but this time all three cases are executed.  No
    # partial lines are shown:
    
    for y in (0, 1, 2):
        try:
            if y % 2:
                raise ValueError("y is odd!")
            if y == 0:
                raise Exception("zero!")
        except ValueError:
            print "y must have been odd"
        except:
            print "y is something else"
        print "done with y"
    print "done with 0, 1, 2"


my_function(1)