It is pretty much a given these days that unit testing increases to quality of software. It increases the quality of code, and makes paying off any technical debt easier and cheaper. Unfortunately, they are also among the first casualties once the release date approaches and crunch time begins. There are many excuses, er, reasons why this occurs and I will not cover them here.
If we assume that unit testing time will be cut at the end then it should be possible to reduce the amount of unit testing we do at the start of the project in order to have more near the end. Assuming that this is true (which may or may not be depending on the project manager) then we need to answer a very interesting question. How can we tell how much unit testing is enough?
Having a code coverage number would be ideal. It is easy to get metrics for that and it easy to grasp. If I said 80% was a good enough number then we could calibrate our automated build to ensure that we hit it. But this doesn’t work in reality. If you set the bar at 80% then the easiest 80% of the code base gets unit tested. This leaves 20% of code (which has a very good chance of being complex) untested, while your trivial methods (e.g. accessors) are sitting at 100% tested. Setting a higher number helps offset this, but it is still not going to hit the intended target.
More complex metrics provide a better guide. A useful metric is C.R.A.P. (Change Risk Analysis and Predictions). It gives methods a score based off of complexity and unit test coverage. It provides a better rule of thumb as code coverage, but it can still be gamed. In fact, any metric that you can think of can be gamed.
Another tactic is to have a unit test for every bug logged. While this is a great idea, it doesn’t help determining if you have enough unit tests. It is too reactive for that. You are relying on your QA staff to determine coding behaviour and that is never a good idea.
Unfortunately there is no good answer to this problem. Every system, and team, is different and has different unit testing requirements. It takes a fair bit of experience and intuition to find out what is right for your project.
I would suggest the followings rules that must, at a minimum, be met:
- All complex code (if it cannot be simplified) should be tested as much as possible.
- All bugs should have unit tests that reveal them, and prove they are fixed.
- All modules that have a higher than average bug count should be tested as much as possible.
- Drop UI unit tests in favour of business tests, since they do not provide as much value.