Here’s a scenario I’ve seen play out over and over again in development shops. It has to do with different opinions on the relative value of unit testing.
You have a stable and well-established team, led by some pretty long-tenured developers. These folks might have titles like “principal developer” or “architect,” and they know both the software and the problem domain inside and out. Over the years, they’ve developed and refined their way of doing things, and management trusts them. After all, they get the job done.
In the same shop, you have a cohort of newer developers. They have fewer years in the industry and are relatively new to the company, but they have a lot of enthusiasm. They come in wanting to implement various industry best practices and things they’ve picked up in other shops.
“We should set up an automated build using Jenkins.”
“And we should also start writing unit tests.”
A predictable dynamic then emerges. The busy, longer-tenured folks feel skeptically toward a barrage of suggested changes. The newer folks feel like the group is a little backward and needs to get with the times. Both sides plead their cases with management. And usually, management defers to the long-tenured folks.
The Argument of Unit-Testing Skeptics
Unit testing isn’t really an open debate in the world of software any longer. Industry opinions skew unevenly, as reflected in this Stack Overflow question. Overwhelmingly, people agree that it’s a good idea. But that doesn’t mean that everyone necessarily does it.
So the unit-testing skeptics in the group don’t argue against the merits of the practice. Instead, they argue that the costs of adoption outweigh the benefits. Both to management and to enthusiasts, they say something like the following.
Look, I’m as much a fan of unit testing in theory as anyone else. But it’ll take a while to implement and our code isn’t set up for unit testing. It’s also frankly a bit overrated as a cure all for our problems.
If we do implement it, we’ll have to spend months getting it going, and it’ll push back our release schedule. So it just doesn’t make sense right now. We should set aside some time later for further investigation.
And that often settles the matter in management’s eyes.
Understanding How Management Thinks
Put yourself in management’s shoes at these organizations. You have an admittedly imperfect operation that has its problems. You miss a fair amount of deadlines and have a lot of production bugs. But the people you trust always get the job done eventually, and they fix the bugs that come up.
A newer, lesser-known commodity is telling you that things are worse than they seem. But don’t worry! They have just the thing to fix it: an industry best practice that everyone says you should adopt.
The more established, better-known commodity, on the other hand, counters that this new approach won’t actually be that great, and it’ll definitely delay upcoming deadlines.
As a manager, the finer points of code testability and automated tests are lost on you. So you look at this simply in terms of risk and reward. One group promises you an unknown return for an unknown cost that you should take on faith. The other group advises against that and offers you more of the predictable status quo.
As is, this is a no-brainer in favor of the testing skeptics.
So if you want to convince management of the value of unit testing and the downsides of the status quo, you need to get better at speaking their language.
A Helpful Metaphor About the Value of Unit Testing
When trying to convince people to unit test, a lot of proponents cite wide adoption among respected industry figures. Or they talk about fewer defects, higher quality code, and less technical debt.
And, while management understands these concepts, they don’t really feel them in a profound way. If you want that profound effect, you have to speak about things like risk, missed deadlines, budget overruns, and plans blowing up unexpectedly. Those things really get their attention.
So when lobbying for the value of unit testing, focus on an often overlooked property of the practice: a flat cost of change. With unit tests, developers have as much confidence changing the code in month twelve as they do in month one of a project. Without it, every passing month brings mounting dread of touching certain parts of the codebase.
Think of a car. A codebase with unit tests is a car that you take for regular inspections and maintenance, and it has a functioning check-engine light. A codebase with no unit tests is one that has no warning lights and one that you don’t get inspected.
Early on in ownership of the cars, you notice no difference. But as time goes by, the no-tests car starts to concern you. You stop taking long trips with it for fear of what will happen. You feel paranoid when you’re in it. Eventually, you stop bringing it anywhere but the grocery store before giving up on it entirely. Well before the end of its expected life, you trade it in for a new one that doesn’t terrify you.
Unit Tests Flatten the Cost of Change
With this metaphor in your back pocket, you can now speak to management (and skeptical architects) about your codebase. Your codebase is the car with regular checkups and a warning light.
Will it be perfect? No, of course not. You’ll always have hiccups and problems from time to time. But with regular checkups and good, early feedback about problems, you can take your road trips without a constantly impending sense of doom.
Perhaps the most important benefit of unit tests is the sense of confidence they inspire in developers needing to change the codebase. They can fearlessly change the code, knowing that an angry red test will let them know if they’ve broken anything. This means that you can expect similar features to take similar amounts of time to implement throughout the project.
All parties to the discussion can relate to the opposite situation, where features take days, then weeks, then months as projects drag on. You could likely even gather data on this from your own project backlog. Then, you can explain that this situation is not inevitable.
Unit Tests Reduce the Cost and Cycle Time of Defects
Drawing on the car analogy once again, you can talk about the savings associated with early detection. If you have a trouble light that goes on when your tire is low on air, you can fix the problem at a gas station with a few coins. You just put air in the tire.
But if you get no such feedback, you might not notice the problem until you’re scraping the rim along the highway. Now the problem costs much more to fix: the price of a new tire and a new rim.
Unit testing has the same effect. If you make a change that flips a test to red, you just correct the mistake. Without that early detection system, the bug sits in the code. Maybe you catch it when running the app, but probably not. It’s up to QA or even the end user to catch it then. And when they do, fixing it will prove much more costly and confusing.
Unit Tests Steer You Away From Wasteful Rewrites and Overhauls
Recall that, in describing the metaphor, I talked about trading in the car with no feedback system. You give up on the thing before its lifetime should expire.
Use this when talking to management. Shops without unit-testing practices disproportionately wind up rewriting their software. It gets so hard to maintain and developers get so afraid to touch it that they eventually throw up their hands and clamor for a rewrite.
When this happens, it’s a complete waste. A lot of organizations accept this as simply the cost of owning software, but that’s not true at all. When you have a flat cost of change and confidence in the software, you can evolve the software to keep up with new frameworks and technologies. Like the car with no warning light, complete rewrites only happen in brittle codebases with deep problems.
Positivity and Experimentation
You now have a convincing metaphor and several business-focused arguments at your disposal for lobbying to unit test. If you were so inclined, you could dive into more technical details: unit tests promote loosely-coupled code, discourage gold-plating, etc. But I wouldn’t do that, given the audience, we’re talking about here.
Instead, find a win for all parties. Long-tenured technical folks might feel threatened and management might be wary of significant time investment for questionable return. Use the car analogy to build your case for the practice on the whole, and then set their minds at ease with the remainder of your pitch.
Propose to just try it on a small scale, in a way that puts no deadlines at risk. Given the benefits that you’ve cited, it becomes pretty hard to say no when you put forth a way to make the investment nearly zero. It also removes some of the discomfort factor of a new approach.
Get the tests in there, maintain them, and wait for the “aha” moment. This moment will come the first time the test suite saves a skeptic from inadvertently committing a regression defect into the codebase. Once that happens, you start to get converts.
Bringing people in your organization around to new practices can be frustrating, but remember to stay positive. Management’s natural skepticism comes from confusion over both risk and reward of the activity. Minimize the risk for them, clearly communicate the reward, and demonstrate as much value along the way as you can. Doing all of this will make it really difficult for them to say no.