Why Do Programmers Fail to Write Good Unit Tests?
We programmers are full of opinions when it comes to unit testing. We don’t always agree about the importance of unit testing or what role it should play. There is also a lot of debate about what makes a good unit test. But before you dismiss unit testing, I’d like to argue that it’s an essential part of what it means to write clean code, and in the long run will make you a better programmer.
I know that more and more programmers are starting to embrace unit tests which is great news for the industry. But I’m also aware that many of us still remain skeptical. And a small part of me understands why. Those who are reluctant to embrace unit testing often claim that good tests are difficult to write They take the time that can be used developing new features. Others take this a step further and question whether there is a link between passing a unit test and good code.
But when you see it in action it very quickly becomes clear that unit testing done well can streamline the execution process and helps development teams build better processes. And perhaps that’s why I’m going all in when it comes to unit testing. I think that once more programmers have a clear understanding of what makes a good unit test, they too will embrace it.
In my experience, however, it’s almost too easy to write a bad unit test, and this just ends up costing you in the long run. Bad unit tests also don’t prove anything, making them very unhelpful. To truly see why I and many others in the industry are so excited about unit tests, you have to interrogate the many misconceptions about what unit tests are supposed to achieve. This is the only way to really see what unit testing can do for you.
What makes a good unit test?
Where many of us programmers go wrong is in failing to differentiate between good and bad unit tests. I believe that if you’re ever really going to see the true benefit unit testing, you must know what makes a good unit test.
While it may seem obvious, many fail to realize that a programmer with lots of experience won’t necessarily write good unit tests. This is partly because writing unit tests and coding requires a different approach. But it’s more than that. Often the quality of these tests is impacted by false assumptions about what unit tests should achieve. The aim of a good unit test is to think about how the code should work in normal and extreme cases, examine and test each unit of code separately, and check that the code behaves as expected.
Here are some pointers to keep in mind for writing good unit tests:
- Each test should be independent of all other tests: Specific behavior should be documented in only one test otherwise if you change that behavior you’ll have to change multiple tests.
- Tests must assert something: It’s vital that you assert anything that’s also asserted by another test as this will yield the test ineffective and won’t prove anything. Each test should have only one assertion.
- Test code unit by unit: Avoid testing units of code grouped together as this can cause unnecessary overlap, and may cause one test to affect another.
- Avoid common setup code for unrelated tests: Unnecessary preconditions which run at the beginning of unrelated tests will impact your results as it means you’re not testing a single unit.
- Avoid testing configuration settings: Keep in mind that your unit test configuration settings are not part of a unit of code. Testing these settings wouldn’t prove anything.
Why you need to unit test
Very few of us, actually none of us are zero-bug programmers. We need to accept that whether due to complexity or simply a mistake, errors will find their way into our code. And that’s where unit testing and different unit testing patterns come in. One of the best ways to improve your code is by writing good unit tests. This ensures there’s a formal process in place and helps us write clean code. Unit testing also plays an important role in helping us maintain clean code as we can easily see which future changes have impacted the code logic and have the ability to refactor the code and redesign it as it grows.
Without good unit testing, you cannot guarantee your code will be clean or consistent. Here are just a few reasons every programmer should consider unit testing:
- Unit tests help reduce bugs in new and existing features
- Unit testing serves as a form of documentation
- Unit testing helps with refactoring
- Unit testing helps with maintaining code
- Unit testing forces you to think about your code more carefully
- Unit testing can make development faster
Any unit test is better than nothing at all?
Some programmers claim that just having a unit test is a good start. I couldn’t disagree more. The quality of the unit test matters more than some are willing to acknowledge. In fact, I often say that if you aren’t going to invest in good unit testing, why bother at all?
A good unit test makes all the difference, and oftentimes is a big asset to the team. While a bad unit test is a costly burden that slows down the development process. It all comes down to how well we programmers understand the basic principles of unit testing. Unit testing has very specific goals and outcomes which we need to keep in mind when creating unit tests. That’s only way we’re going to write unit tests which have any real impact on our work.