As a software engineer, I completely changed my unit testing philosophy over time. Now my tests are much more useful and there are much fewer of them.
I used to write tests for all individual public methods in all classes within a library. All external dependencies were mocked, so each test would only validate the behavior inside the method being tested. I used to expose internal classes to the test library so every piece of functionality could be tested. This way, I had many tests and each individual unit of functionality was tested thoroughly.
I thought this approach was effective until I started reading #TDD books and listened to a few lectures made by industry experts. They proposed a different approach, which I tried and found to work very well. So, this is what I do today:
- Write tests first as much as I can.
- Only write tests against public methods of public classes in a library. The internals will be tested implicitly anyway and they will be included in the code coverage metrics anyway.
- Try to avoid mocking as much as possible and only use it for special cases, such as clients talking to external services.
I'm sticking with this approach because it provides the following benefits:
- Way fewer tests to maintain.
- You don't have to rewrite your tests when you refactor the code or otherwise change the implementation details.
- It allows you to safely refactor your code and verify that doing so hasn't changed any behavior.
- It helps you to spot any pieces of code that are no longer used.
But you may ask, doesn't the name "unit test" imply that you are meant to be testing every unit of implementation? Well, not quiet. Kent Beck, the author of the best-known TDD book, admitted that this was an unfortunate choice of a name. If anything, the "unit" in this context is a unit of behavior, which may involve coordination with several units of implementation. Other people define "unit" as the module, i.e. the whole library, which is fine too.
#softwaredevelopment #softwareengineering #unittests