I had an incident last week where another developer accused me of applying a double standard to contributions on a project. The root cause of the misunderstanding was that he was looking at the unit test that he copied from the other developer, while I was doing a code review of the code he submitted. That got me thinking about code reviews versus unit tests.
Ultimately, it comes down to the quality of the code review and the quality of the unit tests. A lousy code review is waste of time for all parties and is less effective than good unit tests. The reverse is also true, a good code review beats poor unit tests.
What makes a good code review?
A good code review just needs to have the reviewer looking for potential problem areas in the code. There are some tangible, easily quantified and measured things to review and some intangible sort of things to think about.
The tangible things that are important to look at is error handling, input validation, output validation. Coincidentally, this is the type of thing that a good unit test focuses on as well.
The intangible things to look at are around simplicity, style and understanding of the problem area. These are more difficult to measure and quantify. I truly despise the term “code smell” but in some ways it applies to these. You can tell if someone understands the problem by the way that they approach it. As a general rule, when someone understands the problem generally, the solution is simple, like 5 lines of code. For that matter, you can tell if you don’t understand the problem as a reviewer, at which point it ceases to be about review and becomes an educational opportunity which is not the same thing.
It’s not about coding style in the sense of curly braces in the right location and source structure. That kind of thing can be fixed with a script, so who cares? Well formatted code doesn’t have any fewer bugs in it than poorly formatted code. Ultimately, the customer is interested in working, bug free code not in whether or not the behind the scenes area is swept up and looks pretty.
What makes a good unit test?
A good unit test is about exercising the code so that all the common scenarios are covered. At the very minimum, you should be testing the normal operation, inputs missing and wrong, and whether the right output occurs in those scenarios. By output, I mean any event that should occur, whether it’s returning a status message, throwing an exception or signalling an actuator.
What a unit test isn’t is code coverage. It doesn’t matter if you exercise every line of code if you’re not checking the outputs. For that matter, if you’re designing the test for code coverage, then you have a vested interest in making sure that the code doesn’t change because then you have to redo your code coverage analysis.
That being said. there is a place for code coverage analysis. If you have good unit tests, where you’re exercising the normal cases and the cases where you have bad inputs then you do the code coverage analysis. The coverage should be 100%. If it isn’t it tells you at least 1 of 2 things. First, that there is unnecessary code that could be removed. Second, is that it might need to be refactored for things like the separation of concerns. Both of these could be happening at the same time.
In the final analysis
Ultimately, creating a good unit test is really about doing a self code review. Looking at the code to test critically and with an eye for where you might break it in production. Both code reviews and unit tests need to be approached with an attitude of mindfullness. These activities are the kind of thing that people just go through the motions and don’t put much thought into. When that happens, you’re better off not doing either and stop wasting time.