Understand Why You Test
Learning Objectives
After completing this unit, you’ll be able to:
- Explain why you write unit tests.
- Explain how testing helps make you a better developer.
Before You Start
This badge is part of a series on Apex unit testing consisting of the following badges.
- Apex Testing: Review Testing Fundamentals
-
Apex Testing: Prepare for Unit Testing
-
Apex Testing: Write Unit Tests
The content in each badge builds on each other, so make sure to take the badges in order.
Introduction
As a developer, you write code. And to write the best code, you need to test it before releasing it to production. One way to make sure your code is running properly is by using unit tests. Unit tests execute your business logic code with known input parameters and evaluate the output for expected results.
A unit is the smallest logical piece of code that is possible to test. Sometimes the unit is a method, but often it is part of a method. Multiple unit tests often execute the same code but exercise different logical paths through the code. For example, one unit test might exercise the else condition of an if/else block, while another exercises the if condition.
There are three general buckets of software tests: unit, integration, end-to-end. Unit and integration tests are interested in either the functionality of the code, or the code’s ability to integrate with external systems. Unit testing is more specific, focusing on the smallest possible bit of code that can be tested. This means you may have a unit test that focuses on the output of a method when certain conditions are met. End-to-end tests the entire software application from start to finish, simulating a user's interaction with the application.
Additionally, unit tests are often automated to some degree, and they run either on a schedule or in response to an event. For instance, Salesforce runs your unit tests when you deploy from a development environment to production. Because of this, it’s safer to make code changes with unit tests. If you see a unit test failing after a code change, it may mean that the code is not working as expected anymore. Unit tests are your best ally to make your code reliable and trustable.
Why to Test
There are at least three good reasons why developers write tests and a couple that are required. All of which lead to trust in the code.
- Math: The numbers don’t lie.
- Design: Just working solutions aren’t good enough.
- Collective testing: Mutually assured success.
- Confirm: You write tests to prove our software works.
- Code coverage: Salesforce requires 75% overall code coverage for Apex.
This video offers a brief introduction to why developers test.
Math: Numbers Don’t Lie
Writing tests saves development time in the long run. In a 2010 paper on the relative cost of fixing bugs, IBM analysts discuss how long it takes to fix a bug at various times in the software development lifecycle. To illustrate their findings, the analysts describe the relative cost estimates to fix a bug. That is, they describe how long it would take to fix the same bug when it is discovered at different phases of the software development lifecycle.
Their findings are clear: A bug found during the design phase had a relative cost of 1 hour. During the implementation (or active development) phase, fixing the same bug had a relative cost of 6.5 hours. During functional testing, the bug had a relative cost to fix that jumped to 15 hours. A relative cost of 6.5 or even 15 hours is manageable, but the real concern is the relative cost to fix that same bug in production. There, the relative cost to fix it skyrockets to 100 hours.
Not surprisingly, the researchers concluded that bugs are quicker to fix before they hit production.
Of course, testing itself takes time. However, when you consider that fixing bugs takes time away from the creative work of solving problems, if you devote time to catching and fixing bugs as early as possible, you save time later on. Testing can actually accelerate your development timeframe if it prevents even a single production bug.
Design: Working Solutions Aren’t Good Enough
Saving time is great, but there’s a more important reason why we write tests. Testing makes us better developers, which, in turn, leads to better code. One of the hardest lessons developers have to learn (and relearn) is that a solution isn’t inherently good just because it works. The danger of working solutions is that developers often fail to think them through all the way. These solutions may fix the immediate problem, but they also may contain regressions—changes that make the overall product worse. Solutions like this are the cause of most technical debt.
Testing helps differentiate between a working solution and a good one. A working solution can be hard to test. Solutions that are easy to test generally have some traits in common: small and composable methods, focused classes, and well-defined interfaces. If that sounds familiar, it’s because those are also the traits of maintainable and well-written solutions. Writing code with testing in mind means writing code that’s maintainable. And learning to write maintainable software makes us better developers.
Collective Testing: Mutually Assured Success
The first two reasons to run tests apply to all languages and platforms. At Salesforce, there’s another reason to write tests. Tests on the Salesforce Platform help everyone else on the platform. Before each major release, Salesforce runs regression tests on both the current and the soon-to-be-released versions of the platform. This regression testing executes every test in every org. Our regression tests contain every single Apex test class that you write for your org.
This testing is called the “hammer.” During hammer runs, Salesforce executes more than 60 million tests twice. Because your tests help identify platform regressions, they help everyone on the platform. That puts the humble unit test in perspective, doesn’t it?
Again, Why We Test
We test to save time, to become better at our craft, and to build better software, all while helping our fellow developers. We test so we can spend more time solving interesting problems.