Hidden Cyclomatic Complexity due to Parameter Value Coverage

Cyclomatic Complexity

Cyclomatic complexity is the number of branches found in code.

For example:

public int Add(int x, int y)
{
     return x + y;
}

This appears to have a cyclomatic complexity of 1 as there are no branches in your code. One test will give you 100% code coverage.

Detecting Hidden Cyclomatic Complexity

If you have read about Parameter Value Coverage (PVC) you would be aware that some code will do different things without branching in your code. Perhaps the branch occurs in the underlying code. This is still complexity that your code needs to be tested for.

Example 1

Look at the above Add(int x, int y) method. This appears to have a cyclomatic complexity of 1 as there are no branches in this code. One test will provide 100% code coverage if you count coverage by lines.

However, what if your coverage includes different possibilities for the different possible values of your method parameters? What are the possibilities for an int? Well, this example is in C#, so we will assume C# rules. In C#, an int can’t be null. It can be positive, negative or 0. It also has a max value and a minimum value. That is 5 different options that may be involved in Cyclomatic Complexity.

int result = Add(2147483647, 1);

The above code will not result in the answer being 2147483648.

However, the code doesn’t branch if the options are positive, negative, or 0. They code only behaves different if the combination of both values overflow the integer by going above int.MaxValue or below int.MinValue. So the Cyclomatic complexity is 3. It isn’t 1 as most people would assume at first glance.

Example 2

Also look at this simple divide method. This appears to have a cyclomatic complexity of 1 as there are no branches in this code. One test will provide 100% code coverage if you count coverage by lines. However, your code does react differently due to different possibilities for the different possible values of your method parameters.

public int divide(int x, int y)
{
     return x / y;
}

In the above method what happens when either parameter value is 0? Will your code behave the same as if two non-zero values are passed in? Or is there hidden cyclomatic complexity?

Taking into account the hidden cyclomatic complexity, do you still feel this code will never branch? Or do different parameter values cause it to branch? What is the Cylomatic complexity of this method?

If the second value is 0, the code is going to throw a DivideByZeroException. Really, that is the only difference. Since this is divide, it is impossible to overflow the integer, so int.MaxValue and int.MinValue don’t come into play. So the cyclomatic complexity is 2, not 1.

Conclusion

Cyclomatic Complexity is a great tool to measure the complexity of you code. However, failure to test and measure for different possible parameter values can give one a false sense of simplicity and an incorrect Cyclomatic Complexity score.

Branching can occur even in a single line of code. You have been warned!

Leave a Reply

How to post code in comments?