Month of Testing: Why We Test (Part 1 of 3)
This is the first part of a three part blog series about testing. We will be talking about:
Let’s talk a bit about why we write automated unit tests. I believe there are at least three key reasons why we write tests. As developers, we write tests to prove our software works. As Salesforce developers, we write tests because the platform requires 75% code coverage for Apex (but not Lightning!). Over the years, I’ve learned that writing tests is more than just proving it works or checking off a requirement. There is an elegance to designing solutions and solving hard problems, and writing tests is another aspect of that elegance.
Numbers don’t lie
The first reason is pure selfish math. Writing tests saves you time in the long run. In 2010, IBM analysts published a paper on the cost of fixing bugs.
The paper discusses how long it takes to fix a bug at various times in the software development lifecycle. Their findings are clear: a bug found during the design phase had a relative cost of 1. During the active development phase, the relative cost went up to 6.5. During functional testing, the relative cost hiked to 15. The real concern is the last phase, Production. Their findings showed a relative cost of 100 to fix a bug once it hits production. According to their research, bugs are quicker to fix before they hit production. What’s not made explicit is the opportunity-cost. Bugs take time away from the creative work of solving problems. Testing catches bugs earlier, so it frees us to do more problem solving!
It’s true though that testing does take time. Some estimates put a 30 percent premium on testing, yet that 30 percent investment pays rich dividends of fewer production bugs. Imagine a feature your team estimates at eight points. A 30 percent “testing tax” means your estimate bumps from eight to 13. That 13 is still faster than doubling your initial estimate if you had to fix a production bug. That’s another five points of velocity your team has free to work on other features!
Working isn’t good enough!
Math can give us— and our employers— financial incentive to write tests. But there’s a deeper reason we should revel in tests: Testing makes us better developers. One of the hardest lessons I’ve had to (re)learn is that a solution isn’t inherently good because it works. I once deployed a ‘working’ solution, before lunch. Upon returning, I learned that I’d solved the ‘problem’ but also prevented legitimate users from using the application.
The problem with working solutions is that we often fail to think them through all the way. As a result they may contain regressions – changes that make the overall product worse, while fixing the immediate problem. These well meaning, but poorly thought out working solutions are at the root of most technical debt. Testing helps differentiate between a ‘working’ solution, and a ‘good’ solution. A working solution can be hard to test. On the other hand, solutions that are easy to test generally have a few common traits: smaller and composable methods, focused classes, and well-defined interfaces. Sound familiar? Those are also traits of maintainable and well-written solutions. Writing for testing means writing code that’s also maintainable. Learning to write maintainable software makes us better developers.
Everything we’ve talked about thus far applies regardless of language or platform. At Salesforce, there’s a another special reason to write tests: tests on the Salesforce platform help everyone else on the platform as well. Before we push out a big release (think Spring, Summer or Winter), we run regression tests on the platform. These tests contain every single Apex test class you write for your org.
It doesn’t matter if your tests currently pass or fail. When run under the new release, they should pass or fail for the same reasons. We call this logistical ballet the ‘hammer’. During hammer runs, we execute over 60 million tests twice. Because your tests help identify platform regressions, they help everyone on the platform. Puts the humble unit test in perspective, doesn’t it?
So how do I write a good test?
Writing tests gives us more time to solve interesting problems and helps us become better developers. Testing helps us fix bugs before they get to production. It also reinforces proven design principles. Unfortunately, not all unit tests are equal and some are more helpful than others.
Over the next couple of weeks, we’ll be posting a more blog posts on testing. Next, we’ll discuss proper and effective testing of Apex classes. Finally, we’ll finish up with a discussion of the Stub API and some advanced testing topics. I hope you’ll join us for the whole series.
Since we’re starting out with Apex testing, take a look through your codebase. Do you have code that’s hard to test? Check out your team’s definition of done. Does it include writing automated unit tests? Give this question some thought, and we’ll see you again this time next week.
Keep the conversation going on Twitter with #MonthOfTesting.
About the author
Kevin Poorman works as a Senior Developer Evangelist at Salesforce. He focuses on Testing, IOT, Mobile, and Integrations on the Lightning Platform. You can pester him on Twitter @codefriar.