Skip to content
Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
DictionaryCCode Coverage
DevelopmentIntermediate

Code Coverage

Code Coverage in Salesforce is the percentage of executable Apex lines (in classes and triggers) that your Apex unit tests exercise when they run.

§ 01

Definition

Code Coverage in Salesforce is the percentage of executable Apex lines (in classes and triggers) that your Apex unit tests exercise when they run. The testing framework records which lines each test method touches, then reports covered lines divided by total executable lines as a percentage. Comments, method and variable declarations, System.debug calls, and the test methods themselves do not count toward the number. Coverage exists per class and per trigger, and the org also has a single overall figure.

The number matters because it is the gate Salesforce uses before letting Apex reach production. A deployment needs at least 75 percent overall coverage, all tests passing, and some coverage on every trigger. The 75 percent floor is a minimum, not a quality signal: a class can hit 100 percent with no assertions and still tell you nothing about correctness. Many teams treat 75 percent as the line they must clear and aim well above it with tests that actually check results.

§ 02

Reading the coverage number the way the platform does

How the percentage is actually computed

When a test run finishes, Salesforce stores a table of the lines each test executed in each class and trigger. Coverage for one class is the count of executed executable lines divided by the total executable lines in that class. The result shows as a numerator over a denominator, for example 42 of 50 lines, which is 84 percent. Lines that are not executable never enter the math. That includes comments, blank lines, curly braces on their own, method signatures, and variable declarations. Calls to System.debug are also skipped, so logging statements neither help nor hurt the figure. Test methods and test classes are excluded entirely, since they are not production code. One important detail is that the stored coverage numbers are approximate. Salesforce keeps the result from the most recent run of each test, so the figure can drift as you run subsets of tests. The only way to get a true number is to run every unmanaged test in the org or to run a deployment, both of which recompute coverage from scratch across all production code at once.

The 75 percent deployment gate

Before Apex can deploy to production or ship on AppExchange, unit tests must cover at least 75 percent of the executable Apex lines, and every one of those tests must pass. The check is on overall coverage, not on each class in isolation. That means a single class with poor coverage can still pass if the rest of the codebase carries the average above 75 percent, and a high-coverage change can still fail the deployment if it drags the org total below the line. Overall coverage is total covered lines across all production code divided by total executable lines, so larger classes weigh more heavily than small ones. You can read the org-wide figure by querying the ApexOrgWideCoverage object and its PercentCovered field through the Tooling API. The gate is deliberately a floor. Salesforce sets it low enough that any seriously tested codebase clears it, which is why teams that care about defects treat 75 percent as the bare minimum and hold their own bar much higher.

Every trigger needs coverage

Beyond the 75 percent overall rule, Salesforce applies a separate requirement to triggers: every Apex trigger in a deployment must have some test coverage. A trigger with zero coverage blocks the deploy on its own, regardless of how high the org total sits. The reasoning is risk. Triggers fire automatically on record save, so untested trigger logic can corrupt data across thousands of records before anyone notices. Requiring at least some exercise forces a test that creates or updates the relevant records and lets the trigger run. In practice you rarely write a trigger test that stops at the minimum. A good trigger test inserts and updates records in bulk, confirms the trigger handler set the fields you expect, and checks the negative path where the trigger should not act. The minimum requirement is a safety net, not a target. Treating it as the goal leaves the most dangerous code in your org barely tested, which is the opposite of what the rule is trying to prevent.

Coverage is not the same as quality

The single biggest misread of this metric is treating a high percentage as proof the code works. Coverage only records whether a line ran, never whether the test checked the outcome. A test method can call every method in a class, exercise every branch, and assert nothing at all. That produces a glowing coverage number and catches no bugs. Salesforce documentation is explicit that the goal is covering every use case, including positive and negative paths, single records, and bulk loads, not just clearing 75 percent. Real quality comes from assertions. After your test runs the code, use System.Assert methods (or the older System.assertEquals) to confirm the record ended up in the state you intended. Test the failure cases too: bad input, missing required fields, governor limit boundaries. A test suite with thorough assertions and 80 percent coverage protects you far better than one with no assertions and 95 percent. When you review coverage, look past the number to whether the tests would actually fail if the logic broke.

Where coverage data lives and how to read it

You can see coverage in several places, and they do not always agree because each reflects a different run. In Setup, the Apex Test Execution page and the Apex Classes list show coverage per class after a run. The Developer Console highlights covered and uncovered lines right in the source, which is the fastest way to spot exactly which paths a test missed. For automation, two Tooling API objects are queryable through SOQL: ApexCodeCoverage holds line-level coverage per class and test, while ApexCodeCoverageAggregate rolls it up per class. ApexOrgWideCoverage gives the single org total. The Salesforce CLI reports coverage when you run tests, and the VS Code extensions surface it inline as well. Because stored numbers are approximate and tied to the last run of each test, custom dashboards usually query these objects right after a full test run in a continuous integration job. That gives a consistent snapshot rather than the drifting figures you get from running tests piecemeal in the UI throughout the day.

Coverage during deployments and CI/CD

Deployments recompute coverage as part of the process, so the deploy is the moment of truth rather than the numbers sitting in Setup. When you deploy through the Metadata API, Salesforce DX, or Change Sets, you choose a test level. RunLocalTests runs every test in the org except those from managed packages and is the common choice for production. RunAllTestsInOrg includes managed-package tests. RunSpecifiedTests runs only the classes you name, which is faster but requires that the listed tests still satisfy the coverage rules for the changed code. NoTestRun skips tests and is not allowed for production. Mature teams wire these into continuous integration so tests and coverage run on every pull request, long before a change reaches production. That turns the deploy gate from a late surprise into an early signal. A pull request that drops coverage or breaks a test fails the pipeline and never merges. The discipline keeps the org-wide number stable over time, because new code arrives with its own tests instead of quietly eroding the average until a deploy finally fails.

Common pitfalls that trip teams up

A few patterns recur often enough to name. The first is coverage-only testing, where developers write tests that touch lines without asserting anything just to clear the gate. It passes deployment and prevents nothing. The second is silent erosion: new code lands without matching tests, the overall percentage creeps down, and nobody notices until a deploy fails and blocks a release under time pressure. The third involves managed packages. Subscribers cannot edit code inside an installed managed package, and that package brings its own coverage that you neither control nor need to cover. A related trap is relying on SeeAllData or hard-coded record Ids in tests, which makes coverage look fine in one org but fail elsewhere because the data is not there. The cleanest defense is a habit: write the test with real assertions at the same time as the production code, run the full suite in CI, and treat any drop in coverage or any new trigger without a meaningful test as a blocker rather than something to fix later.

§

Trust & references

Sources

Cross-checked against the following references.

Official documentation

Straight from the source - Salesforce's reference material on Code Coverage.

Was this entry helpful?
Help us write better definitions. Quick reactions or detailed edit suggestions.

About the Author

Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.

§

Test your knowledge

Q1. What does Salesforce Code Coverage actually measure when Apex tests run?

Q2. Why is a high Code Coverage number alone not proof of real test quality?

Q3. What coverage range do mature Apex teams typically aim for beyond the platform floor?

§

Discussion

Loading…

Loading discussion…