Learn About Why We Test
After completing this unit, you’ll be able to:
- Define what a unit test is.
- Explain why we write unit tests.
- Explain how testing helps make us better developers.
As a developer, you write code. Unit testing is the software development practice of writing additional code, called unit tests. These 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, Functional, and Integration. Functional and integration tests are interested in either the functionality of the code, or the code’s ability to integrate with external systems. Unit testing, on the other hand, is similar to functional tests, but more specific, focused 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. 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.
This module covers the ins and outs of writing useful unit tests on the Lightning Platform. Each unit has a short video to introduce a concept, along with hands-on exercises to help you master these skills. Ready? Let’s jump in.
There are at least three reasons why we write tests. This video offers a brief introduction to why we test.
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, they 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 life cycle.
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.
Saving time is great, but there’s a more important reason why we write tests: Testing makes us better developers. 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.
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.
We call this testing the “hammer.” During hammer runs, we execute 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?
So, why do 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.