Common Misconceptions with Unit Testing
My analysis after going through a ton of hot debates
Maintaining 100% code coverage
100% is the benchmark to chase when getting started.
But with complex codebases with many dependent components and convoluted legacy design, it will be very hard to mock or fake the dependencies & maintaining them will also come at the cost of productivity.
In reality, you at least should write unit-tests for all the features, and business logic in your codebase, and the code with the highest risk on the business. While ensuring the overall functionality is also covered at some level, either by unit-tests as well or integration tests.
Notably, dynamic programming languages like ≤Python3.9 or Node.Js can benefit from a heavily unit-tested codebase since they lack the natural type system of static languages.
So, the benchmark code coverage percentage should exist which should be maintained by devs. But it is not always 100% and it can vary based on the type of project, choice of tech-stack & desired code velocity.
Unit-tests coverage metric equals reliability or maintainability of code
Just because code is touched during the test process doesn’t necessarily mean it has been tested. Coverage merely suggests the portion of the codebase whose lines were touched by any of the tests.
A high-quality code should have high-quality tests. There is no AI model yet to assess code quality, there are guidelines and unavoidable hard learning curves only.
Unit-tests ensures performance
No, not unless the unit-tests are particularly verifying performance, since the unit-tests are verifying only a unit-code at a time and without dependencies.
A code with O(1) complexity & O(n) is good enough for unit-tests to pass as long as its result is as expected.
Integration tests are more suited for evaulating code performance.
Integration or end-to-end tests are optional
Unit-tests significantly improve code-maintability and somewhat reliablity.
Where the integrations tests actually verify the reliability of the code change with respect to the entire system, actual end-to-end feature and behaviour of the whole system. Integration tests have bigger immidiate gain!
Integration tests are just as important if not more.
TDD is better than writing code followed by its unit-tests
Test driven development or TDD is a practise where the code for tests is written prior to the actual code.
This requires developers to define the complete functionality as a problem statement and then write the best possible solution code for it.
TDD is natural and best when fixing bugs or writing complex algorithms, as it provides a quick feedback loop to verify the ideal solution.
But writing tests requires a different coding style then writing code for features, so staying in the “flow” is more productive for some, so not objectively best.