When is acceptance-only testing a good idea, and how can its problems be overcome?
In a recent post, I espoused some of the benefits my team enjoyed by reducing our test-base to a single layer of acceptance tests, with no separate unit or integration tests. It caused some minor controversy, which was not to be unexpected. At the time, I knew I had left out some details for brevity’s sake. In this post—spurred on by some interesting questions and commentary—I’d like to offer a more constructive view on the subject, and dig a little deeper into the nitty gritty of how we made it work.
I’ll also point out some other hidden benefits of moving to acceptance-only testing, and suggest synergistic practices that can help decide if this is the right approach for your project.
After-the-fact unit testing requires us to find the seams along which code can be isolated and tested. Where those seams don’t exist, the temptation is to refactor code until they do, using patterns like dependency injection, and following SRP and other SOLID patterns.
Test-first unit testing aka TDD naturally tends to maximise seams, and results in highly decoupled code with small, specific tests. TDD must result in 100% unit test coverage, if practiced according to the gospel. In other words, TDD results in the best kind of code for later modification without risk, and the best tests for detailed, granular feedback. Unit tests also tend to run very quickly, sometimes fast enough to run every time you hit “Save”.