Salesforce enforces minimum Apex test coverage before deployments to production succeed. The numbers are deceptively simple — most candidates know the headline figure but few know the edge cases.
The headline rule
- 75% code coverage across all Apex classes and triggers in the org, calculated org-wide.
That’s it for the headline. But there are several catches.
The hidden rules
| Rule | Detail |
|---|---|
| Every trigger must have ≥ 1% coverage | Even though the org-wide average is 75%, every individual trigger needs at least one line covered. A trigger with 0% blocks deployment. |
| Tests must contain assertions | Salesforce checks for at least one System.assert* call per test. Calling code without asserting doesn’t count as a test, and triggers a warning (not a deploy block, but flagged by Code Analyzer). |
| Test methods must complete | A test method that throws an uncaught exception fails. Failed tests block production deploy regardless of coverage. |
| Coverage of test code itself doesn’t count | Lines inside @isTest classes are excluded from both numerator and denominator. |
How org-wide coverage is computed
org_coverage = covered_lines_in_production_apex / total_lines_in_production_apex
Comments, blank lines, and method signatures don’t count. Only executable lines. The platform calculates this fresh on every test run.
You can see per-class coverage in Developer Console > Test > New Run > options, or via the Tooling API:
SELECT ApexClassOrTriggerId, NumLinesCovered, NumLinesUncovered
FROM ApexCodeCoverageAggregate
Coverage is NOT enough
The 75% bar is necessary for deployment. It is not a measure of quality. A test like:
@isTest
static void doesNothingButCovers() {
AccountService.complexMethod(null);
// No assertion — 100% covered, 0% verified
}
…covers lines, asserts nothing, and provides no regression protection. Senior reviewers look for:
- Coverage plus meaningful assertions
- Coverage of error paths (try/catch branches)
- Coverage with bulk data (200 records, not 1)
- Coverage that exercises the same code under different starting states
What blocks a production deployment
- Org-wide coverage drops below 75% after the deployment
- Any class or trigger in the deployment has 0% (well, 0% on triggers — classes don’t have an individual minimum but contribute to the org total)
- Any test in the org fails (Salesforce runs all local tests by default during a deploy)
- Apex compilation errors
What changes when using Run Specified Tests?
In a deployment, you can pass RunSpecifiedTests with a list of test class names. Only those tests run, but the org-wide coverage must still be 75% based on cached results from previous test runs. If the cache is stale, you’ll get unexpected failures.
RunLocalTests runs all tests in your org (excluding managed packages) — the safer default for production.
Apex Code Analyzer signals
The Salesforce CLI’s Code Analyzer flags additional quality issues:
- Test classes without
@isTestannotation on the class - Test methods with no assertions
- Hardcoded IDs in tests
SeeAllData=trueusage
None of these block deployment by themselves, but they should be fixed before code review approval.
Common interview follow-ups
- Why is it 75% and not 100%? — Salesforce picked a number that’s hard enough to require effort but not so high it forces busywork. Most mature orgs achieve 85-95%.
- Does this apply to sandboxes? — No. Sandbox deployments don’t enforce 75%. Production does.
- What about Flow coverage? — Flow has its own coverage requirement (50%) starting in Spring ‘23, separately enforced.
Verified against: Apex Developer Guide — Code Coverage Best Practices. Last reviewed 2026-05-17 for Spring ‘26 release.