Many companies today want developers with unit testing experience. Even though unit testing had existed for many decades, some developers still don’t know how to write them.
When I started coding as a self-taught developer, I didn’t come across unit testing, and later when I started to work with other developers, I heard few mentions. That’s when I started checking what it’s all about.
Once I started writing unit tests I started to see the benefits. One of the things that I like about it is that I can detect any bugs early on during the development. My tests start failing for the method or function if there is a bug. From the warning and error logs of the test, I can determine what went wrong and help me to fix it before I commit the code. Unit tests have increased the confidence in my code and this resulted in less number of defects getting shipped into production.
Later I faced another problem. I was told to target a certain percentage of test coverage on all the lines of code. So I started focussing on fulfilling the requirement and found that the number of tests was increasing. I was writing tests just to cover the lines of code even for the lines that were too silly to test. I found ways to manipulate test coverage results. Another issue was that the tests were getting complex as it was interdependent on other libraries or external files in the project. I also found that some of my tests were affecting the results of other tests. When a simple logic was updated the whole test suite failed. It became unmanageable.
This could be the story of some developers and at this point, they would start hating unit tests and feel that it is a total waste of time writing and maintaining them.
The problem lies in the way one writes unit tests. I realized it the hard way.
So here is how I approach it now.
- Test one behavior at a time.
- Use test doubles (mock) for external dependencies, so that the focus is on testing the function's behavior alone.
- Test in isolation, ie there should be no relation between tests, it should be able to run independently and give the same result as compared to running the whole test suite.
- Focus on testing the output and less on the implementation details.
- Test all conditions, i.e all if and else conditions, and with variants of inputs.
- For discoverability write tests in the order in which it appears in the code and scope multiple tests of the same function in a block.
- Write good test descriptions, as you have to read them later.
Keeping the above points in mind helped me write clean tests and avoid false positive results.
There may be a different approach that you follow that helped you manage tests. If so share it in the comments.