This answer is not intended to teach you everything about writing unit tests, nor to specifically answer every question, but to provide a quick summary and links to the resources that will help you move forward and develop more specific questions that SFSE can assist with.
Overview
Unit (and integration) testing is a big topic, but it starts with a small set of principles. If you've never written a unit test before, we strongly encourage you to complete the Unit Testing on the Lightning Platform Trailhead module and read at least the Month of Testing series. These materials and others are linked under Resources, below.
Fundamentally, testing comprises three steps, all of which take place within the context of a unit test:
- Creating test data as input for your code, which is designed to ensure that a specific logical path is executed. This can take the form of values in memory or of creating and inserting sObjects.
- Executing that code, meaning that that specific code path runs within a method annotated with the
@isTest
annotation.
- Writing assertions to demonstrate that the results of the code are correct and as expected for the given inputs.
Then, all code that is executed under step (2) is counted as covered under Salesforce's code coverage metrics. Code coverage is a side effect of high quality unit tests. Salesforce uses code coverage as a proxy to measure the presence of unit tests in your deployments.
Unit testing principles are quite general, and most Apex code is not special in the sense of requiring unique approaches to create a successful test. Techniques for implementing tests that perform all three steps are taught in the resources we include below.
Test Isolation
On Salesforce, all unit tests are executed in an isolated context. In this context, your code cannot see data in your organization, including ordinary records as well as Custom Settings. All data must be created via the unit test or @testSetup
method.
Metadata records, including Users and Custom Metadata, are visible in test context.
An older annotation, seeAllData=true
, allows tests to see all data in the Salesforce org. Use of this annotation is strongly discouraged for new unit tests, and is considered a very bad practice. It's important instead to follow the first step above, by designing test data as input for your code. This practice makes unit tests self-contained and repeatable, and insulates them against fragility stemming from data changes.
Smoke Tests (Tests without Assertions)
Unit tests that don't contain assertions are often called smoke tests. These tests have very limited value, because they show nothing other than that your code does not crash under a specific set of circumstances. They don't prove the code works or does what it's intended to do.
Resources
Trailhead
Apex Developer Guide
- Testing Apex
- The
Test
class reference, which includes a variety of testing-related utility methods, including Test.stopTest()
and Test.startTest()
, as well as methods for setting static SOSL results, controlling audit fields, working with mocks and stubs, and other tools.
Blogs and Articles
- Month of Testing series from the Salesforce Developers blog.
Dreamforce Video Content
Third-Party Testing Frameworks (Advanced Topics)
- ApexMocks, an open-source mocking framework for Apex.
- Force-DI, a framework for pervasive dependency injection.