We have other guides on the common mistakes when writing unit tests, and it’s important to understand and recognize when we’re making these mistakes. But even more important is learning how to avoid them in the first place. In this chapter, we’ll discuss exactly this!
Use good metrics
In testing, like other parts of our lives, we get hung up on the wrong metrics. We want a comprehensive unit test suite, but what does comprehensive mean to us and our project? There’s not a single answer to this question, but by picking the correct metric(s) to measure yourself and others by, you will be able to provably deliver a valuable unit test suite.
Summarize the purpose and value of each test
The first principle of Test Driven Development (TDD) says to write your test suite before writing your code. Using this approach, we have to think about the complete behavior of the code prior to writing a line of it. Without existing code clouding our judgement, we end up writing tests based on specific expected behaviors, which prevents writing tests for the sake of writing tests, or chasing arbitrary coverage targets.
You don’t have to be doing full-on TDD to avoid this mistake. When you start writing tests, try adding a couple of lines to the test: one giving you the purpose of the test (“What is it trying to test?”) and the other saying what the value is (“Why will the end user will care if the test fails?”). If you cannot answer one or both of the questions, then ask yourself: Should this test exist?
Treat test code the same as production code
Test code will cause the build to fail if one of the tests fails. It may not actually be used by the user, but in a modern DevOps environment where you are trying to do multiple releases per day, having poor quality test cases will lead to frustration through intermittent build failures.
This is why it’s important to apply the same coding standards to your test code as your production code. The number of tools, such as linters, that ignore test code is astounding. Just like maintaining production code, someone else on the team (or future you) will have to debug and maintain your tests. You want to make this as easy as possible. ‘Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.’
There is no magic bullet that will ensure you always write the best test cases possible. However, like anything else in the art of coding, it’s important to set a baseline for what is good enough for your needs and ensure that you always stay above this line. With this in mind, and a culture that makes testing as important as writing production code, you won’t go wrong.
Check out the rest of the guide:
- Intro: What are the different types of tests?
- Chapter 1: How to write your first unit test
- Chapter 2: How to measure code coverage
- Chapter 3: How to build a complete test suite
- Chapter 4: Mocking in unit tests
- Chapter 5: Finding the time and motivation to unit test
- Chapter 6: Unit testing mistakes to avoid
- Chapter 7: How automated unit tests speed up continuous integration
- Chapter 8: How to deliver on the promises of DevOps
- Chapter 9: Why imperfect tests are better than no tests