Kent Beck told me years ago, if the code does not need to work, then there is no need to test it. He continued and observed, why bother writing it if it does not need to work. Since hearing that and discovering how frequently I make coding mistakes, I want thorough tests.
Maybe you are asking yourself “I’ve got integration and system tests, why do I need unit tests?”. The answer is simple, simple math.
The only practical way to know that every line of code is doing what you think it should do, is to have unit tests that exercise and check each line. Higher level tests, because of the number of combinations, can not practically test each line as the system grows larger and object interactions increase. For example, how many tests are be needed to thoroughly test these three objects if you test them together?
Did you do the math? It requires multiplication. You would need thousand tests to test this simple network of objects. In most cases, it is not practical. Who would bother to spend the time to write 1000 tests for such a simple system? (Maybe someone in medical electronics, aviation or space travel.)
No consider a unit test strategy for the same three objects.
The numbers game works in favor of unit testing. Addition is needed instead of multiplication to calculate the test count. You need a total of 30 unit tests to fully test each object. Then you’d be smart to write the necessary higher level tests to check each interface is being used properly and the system is meeting its requirements.
Its not a matter of needing one and not the other. Unit tests and higher level tests are both needed. They just serve different purposes. Unit tests tell the programmer that the code is doing what they think it should do. They write those tests. Higher level tests (by whatever name you like: BDD, ATDD, Acceptance, System, integration, and load tests) cannot be thorough, but they demonstrate that the system is meeting its requirements.