Search code examples
unit-testingtestingcyclomatic-complexity

Cyclomatic complexity calculation - concrete example


Let's suppose we have the following code:

public void testIt(boolean a, boolean b){
   if (a){
   ...
   }
   if (b){
   ....
   }
}

As I know there are three methods to calculate. I will use two of them: region formula and the rule of thumb.

Using region formula we have two regions if(a){this is the first one} and if (b) {this is the second one}. So CC = two regions +1 = 3.

The rule of thumb is from Testing for ISTQB Advanced Level Technical Test Analyst vol 3 book:

Now, this is all simple enough for a small, modest method like this. For larger functions, drawing the graph and doing the calculation from it can be really painful. So, a simple rule of thumb is this: Count the branching and looping constructs and add 1. The if statements, for, while, and do/while constructs, each count as one. For the switch/case constructs, each case block counts as one. In if and ladder if constructs, the final else does not count. For switch/case constructs, the default block does not count. This is a rule of thumb, but it usually seems to work.

So according to this rule CC = two if conditions +1 =3.

However, on stackoverflow in chat with one user I was said that the CC of this code = 4 (he used the third method) and the following image by that user was provided: enter image description here

So what is the cyclomatic complexity of this code? 3 or 4 or?


Solution

  • Cyclomatic complexity of this code is 3, according to definition

    M = E − N + 2P,
    

    where

    E = the number of edges of the graph.
    N = the number of nodes of the graph.
    P = the number of connected components.
    

    M = 7 - 6 + 1*2 = 3

    In relation to software testing it means:

    M is an upper bound for the number of test cases that are necessary to achieve a complete branch coverage.

    M is a lower bound for the number of paths through the control flow graph (CFG).

    All three of the above numbers may be equal: branch coverage <= cyclomatic complexity <= number of paths.

    So, you need 2 tests to provide branch coverage. But it does not mean that it will cover all paths.

    To cover all paths here you need 4 tests.

    To understand it, consider following update to your code:

    public String testIt(boolean a, boolean b){
        String s = "";
        if (a) s = s+"a";
        if (b) s = s+"b";
        return s;
    }
    

    to cover both branches you can test (true,true) and (false,false)

    but number of possible paths (outcomes) is 4:

    "", "a", "b", "ab"
    

    which absolutely fine with formula above 2 <= 3 <= 4