Reputation:
Clearly, I don't understand unit testing. This is fine, considering I've never done it before. I'm starting a new project, and wanted to bake unit testing into it from the beginning, so I'm looking to learn.
I had always equated unit testing with code coverage, thinking that you should have unit tests which cover every function/method in your application, but clearly this isn't the case and I've completely misunderstood the concept.
So,
Upvotes: 18
Views: 5768
Reputation: 756
I had always equated unit testing with code coverage
That is not entirely wrong. Unit tests / any other sort of test automation have only one truly undeniable benefit that holds in 100% of cases: they actually run the code i.e. they cover it. Compiler doesn't run the code. Static code analysis doesn't run the code. Obviously reading the code won't make it run. Automated tests do run the code (as well as manual debugging).
Any other claimed benefits are only potential and fully depend on competence and best intentions of those who write tests.
thinking that you should have unit tests which cover every function/method in your application, but clearly this isn't the case
Correct, not every single line of code is worthwhile to be automated to run during build.
So,
- What sorts of functions benefit from unit testing?
- What sorts of functions shouldn't be unit tested?
With above in mind, at least two conditions should hold:
possibility of error can't be eliminated statically (try to design code the way that makes invalid states and scenarios impossible to represent and save yourself from heaps of unit tests)
possibility of error is not low, e.g. code is not trivial / very cohesive etc.
OR
this is a mission-critical component / deploying an error has dire consequences. In this case it's worth to be a paranoid, even if possibility of error is extremely low.
OR
Code is a part of published / externally visible contract e.g. a library interface. In that case even primitive tautological tests are useful as they act as executable requirements / protect you against unintentional changes of published contracts (sort of specific case of a previous bucket of mission-critical tests).
OR
Writing a test is actually easier than reaching this code manually, can be well true in large monolithic behemoths. It doesn't mean you have to keep the test around forever, feel free to delete it later if it incurs large maintenance costs. But code must be run and results must be observed and accepted at least once before deployment, of course.
Above is true as of my best current knowledge provided that one's priority is to be pragmatic. If priority is to have good excuses for sloppy job then aim for 100% coverage and other religious test practices are perfectly justified (think "it's not my fault - all tests were green!")
Upvotes: 1
Reputation: 22190
Unit testing is a tool, and there many approaches on how to use it. Here is my approach :
I write my unit tests against Service and DAO signatures, and not so much against DTOs and entity types. Most of the value types will be indirectly tested. equals and hashCode methods in DTOs and entity types should be tested though.
I use both pure unit tests with mocked dependencies and integration tests with the full backend. For proper coverage, one needs both.
Upvotes: 0
Reputation: 218827
I don't have a complete answer (I'd love to hear anybody who does, honestly), but can at least toss out a few points...
Upvotes: 6
Reputation: 1880
According to TDD (Test Driven Development) methodology one should test every public function, and every path of execution in that function.
Upvotes: 1