A few common reasons used to justify not writing unit tests.
1 - the developers are elite/rock-stars/gods and write code which does not need to be tested.
Let's assume for a moment the assertion above is true and that non-trivial code can be written so perfectly that is is bug free (unlikely...). Even then the value of a test suite is not only about checking quality of the code when it is written. It's also about:
- Preventing regression bugs when that same code is changed further down the line.
- Documenting the behaviour of the application by demonstrating how the api should be used, and what results are expected for each use case.
- Ensuring quality of the design. A program which has been written with testing in mind from the start will almost necessarily exhibit sound design characteristics: loose-coupling and high cohesion in particular. Otherwise testing becomes so overly difficult and messy that it is close to impossible.
2 - Unit testing slow us down.
The reasoning here is that time which is spent writing unit tests could be better spent on other tasks such as bug-fixing or adding new features to the app. This is undeniably true.... in the short term. In the medium to long term all the code that has been churned without being properly tested is likely to break.
These breaks will be costly. At minimum there is a damage to the firm's reputation, not counting the time being spent debugging the issue and fixing the code. So it's a trade-off, speed vs quality of code.
These breaks will be costly. At minimum there is a damage to the firm's reputation, not counting the time being spent debugging the issue and fixing the code. So it's a trade-off, speed vs quality of code.
3 -focus on end-to-end tests (a.k.a system tests) rather than unit tests.
Since unit tests take time to write and maintain an alternative is to test at the highest level possible and simply check that the overall flow of the application is as expected, without testing the details of how the flow is generated. This is seen as a more efficient way of testing because these tests focus directly on the output of the application, which is what matters to the user. A few problems with this approach:
- end to end tests are slow: testing the whole application is order of magnitude slower than testing a single class, especially when there are dependencies to third-party systems involved (cost of network calls, database access...)
- end to end tests are brittle: a chain is only a strong as its weakest link. Any change in the chain of components used by the application can alter the expected user output. Finding which component is responsible for the change in behaviour can be tricky to spot and debug.
- end to end tests are complex, especially in a distributed environment where it is necessary to initialise each node or component to the specific state expected by the test. In particular test static data needs to be created, and maintained in line with changes to the application logic. (think database reset between tests).
- also see arguments advanced above on point 1) - lack of unit tests also impacts the quality of the code, likelihood of regression and self-documenting feature.
4- Finally there are a few circumstances when unit tests are not strictly required:
- when building a prototype, maybe with the sole purpose of checking the technical feasibility of a new design and the code is bound to be thrown away.
- some features cannot be reliability tested at the unit-test level. Hardware failover, recovery from database failure, or more generally any scenario involving several machines, cannot be reliably tested by unit-tests running on a single machine and jvm.