How many unit tests?

There are several advantages in developing unit tests:

  • finds bugs early
  • You trust your code
  • Makes your code simpler, because you probably refactor it to make the tests easier to develop
  • It documents your code. The name of each unit test almost describes the feature
  • You will be more confident to change the existing code
  • It documents your code
  • The unit tests when running they are debugging your code
  • It makes it easier to troubleshoot production issues. You can reduce the scope of the analysis
  • It reduces costs. Code with fewer bugs reduces the costs of troubleshooting later
  • They execute faster than the other tests. You can use them as a rapid verification of the quality of our code.

Looking at all these advantages, we surely start to think we should develop as many unit tests as possible.
But the truth is, you should develop just enough unit tests.

How many unit tests are enough?

Let’s first analyse the consequences of developing unit tests:

  • Every unit test increases the coupling between your production code and the unit test. Meaning, every time you change the production code, you need to update one or several unit tests.
  • Developing unit tests takes time, not only developing but maintaining them too
  • It is very easy to start testing code that doesn’t need testing, such as the use of external frameworks. I see this a lot!
  • The unit tests, test the algorithm, not the functionality. You will prefer to use that time to develop integration tests, they cover more code with just only a few tests. Be aware they require some preparation, though (a future post)
  • Can create a lot of coupling if you use have to use a high quantity of mocks

Looking at all these advantages and disadvantages, I usually advise:

  • target a coverage around 70%, more than this starts to create a high couple between the code and the tests
  • Use an approach of risk-based testing, meaning
    • choose to test the branch in your method or unit that covers the most important functionality
    • cover the code that cannot fail because it brings costs to the company
  • Develop them at the same time as you develop the method, otherwise, the code will become complicated to test. Use a TDD-ish approach.