Written by Erik Dietrich
Over the years, I've helped a lot of organizations install and improve their unit testing practice. As you can imagine, I've also heard a lot of concerns over, and objections to, unit testing. At the top of that list? The extra time it will take.
Let me start by saying that this is an understandable and rational concern. You have a team of people already logging their full 40 hours per week building your software. And you're not going to make them work overtime to start unit testing. So it only stands to reason that starting to unit test means they'll have to stop doing some other valuable activity. And because people don't do superfluous things that you can cut, this will mean delays and budget overruns.
Unit Testing Adoption, Reconsidered
I'll go into detail about how unit testing helps your business, but, before I do, I'll ask you to change your thinking on the subject just a little. Specifically, try not to think of unit testing as a disjointed, separate activity. You're tempted to think of it that way because of easy separation of software implementation and quality assurance in traditional shops. But unit testing doesn't work that way. Developers writing unit tests are really just writing code differently.
I'll use an admittedly imperfect analogy so that anyone reading can understand, developer or not. Let's say that a programmer resolved to write code with better, clearer variable names that made it easier for maintainers to understand.
You wouldn't really think of that as a separate activity from writing code. In other words, it's not as though this developer spends two weeks writing code normally, and then 3 days renaming stuff. Instead, the developer just spends a little more time, here and there, thinking through the names.
You'd find yourself less inclined to object to this resolution. It's harder to separate this naming effort from normal activities, and harder still to quantify it. But, perhaps more importantly, you shouldn't bother trying to quantify it. Worrying about the team at this granularity of technical practice is micromanaging, and, if you feel the need to do that, you probably have bigger problems than variable naming.
Leaving Developers to Know Their Business
Developers spend time doing all sorts of things that aren't literally, actually typing code. They draw designs on whiteboards or pieces of paper. They squint at a debugger and run experiments on code to increase understanding. Perhaps they even, internet policy permitting, look up answers on Q&A sites like Stack Overflow. You'd probably be surprised at how little of coding time is spent literally typing they keystrokes that make up the code.
And that's for the best. When someone comes to fix your furnace, hopefully, you start asking him why he has blue grips on his socket wrench or why he's spending valuable time checking the electrical lines when you have a gas powered furnace. Instead, you hire a service provider you think you can trust and then, well, trust him.
The same applies to the development team. You trust them to compile the code the right number of times and to know when to debug something versus ask a question on Stack Overflow. And, similarly, you should trust them to spend their time wisely when it comes to automated unit tests, assuming they've learned how to write them.
In the end, unit testing as a practice won't hinder their day to day development any more than compiling their code or looking at Stack Overflow does. The only remaining question, then, becomes whether to invest in getting the developers good at writing unit tests. For the rest of the post, I'll make the case that this investment is indeed worth it.
The Test Suite Reduces Deployment Risks
If you have developers writing good unit tests, you'll develop a nice, robust unit test suite over the course of time. Developers will run this test suite constantly, and they'll even have the team build to run it in a production-like environment.
With each test they write, they secure just a little bit more of the application's behavior against regressions. Regressions typically happen when developers change something and accidentally break functionality that worked previously. If you've lived in the software world, you probably know how maddening this is, especially when the bug makes it to production and users find it. Oops.
Your unit test suite guards assiduously against these regression defects. And, it provides concrete evidence that new functionality behaves as expected. All of this adds up to the very real business outcome of deploying with more confidence. You're far less likely to need to dedicate time to support calls, triage, and patching. And you'll look better to your users.
Tighter Feedback Loop for Time Savings
The benefits, however, extend beyond what happens following a deployment. A nice test suite also helps you realize labor-savings benefits.
In the Agile coaching world, you'll find a pretty iconic graph of the cost to fix a defect as a function of time. If you catch a defect as you write the code, you can fix it immediately, as you would with a typo. But if you don't catch it, and you commit it to source control, things get more expensive. Then someone in QA might catch it during their hours of testing. They log it in the bug tracker and kick it back to the development team, who spends a good bit of time reproducing the issue, tracking it down in the code and fixing it. And, if months or years elapse and the defect is discovered in production? Well, by then, you've probably built on top of it, making the cost of change catastrophic.
A unit test suite makes you much more likely to catch errors sooner than later. It does this by tightening the feedback loop. So with a good test suite in place, you're far less likely to spend disproportionate amounts of time tracking down, reproducing, and fixing issues and the code you've built on top of them.
More Business-Friendly Software Architecture
Speaking of the cost of change, unit testing helps with this in another way as well. Michael Feathers once gave an excellent talk, entitled "The Deep Synergy between Testability and Good Design," and I completely agree with his arguments. Testable code is better code, as measured by how easy it is to change that code.
Testable code tends to have "seams" that serve as nice points of modularity in your application. It's hard to test code that writes to databases and files, so committed unit testers will "mock" files and databases to facilitate their testing. As a byproduct, it becomes easier to swap a database or file out in that application than in one that doesn't bother to create a seam between application code and the database.
And, it probably won't surprise you to learn that people who write a lot of unit tests get good at writing testable code. That happens by simple practice optimizing their own efforts. The upshot is that shops focusing on tests tend to have architectures that make future changes easy. This, in turn, helps the business by keeping the cost of change and the software's total cost of ownership lower.
Credibility, Since Office Politics Are a Reality
I'll close by offering one last, more philosophical benefit. It feels weird to say, but it does reflect reality. Being part of or managing a group that unit tests has positive implications for your career.
Like it not, the software world has spoken and automated testing is considered the right answer. As such, people with experience developing in this style or managing it will be more marketable. That's a personal benefit for individuals, but it also adds credibility to the group as well. Clients, customers, executives, and really any stakeholders in a software group will find themselves more inclined to give them the benefit of the doubt if they make good faith efforts at adopting what the industry deems best practices.
Make no mistake. Unit testing has plenty of tangible benefits, including the ones I've outlined here. It will make the team better, save the business money, and have good implications for the careers of all involved. As they say, a rising tide lifts all boats.