What does the coverage error mean?
Production needs 75% Apex coverage across the org, and every trigger needs at least some. With RunSpecifiedTests, each class you deploy needs 75% on its own (Salesforce Help). The deploy stops when the number is lower. Salesforce prints which class missed, or the org-wide average, depending on the test level you picked.
In the message above, the class has three methods and one test calls one of them, so the result is 33.333%.
Why is my coverage low when the sandbox deploy worked?
Usually one of these.
- The class is new and nobody wrote a test for it yet. Quick fixes written straight into a sandbox often land this way.
- The test exists but only covers the happy path. Every
ifbranch you skip leaves lines uncovered. - The test passes in the sandbox because it reads data the sandbox has. In production it finds nothing and fails, so the lines never run. Records created inside a test are not marked as viewed, so a query that filters on
LastViewedDatereturns nothing unless you addFOR VIEW(Salesforce Help). - You picked
RunLocalTestsand some old class in the org drags the average down. Your own class can be at 100% and the deploy still fails.
How do I fix it in Setup?
- In the source org, open Setup, search for Apex Classes, and click Estimate your organization's code coverage. This gives you the org-wide number.
- Open the Developer Console, then Test, then New Run. Pick the test classes and run them.
- Open the Overall Code Coverage panel. Double-click a class. Covered lines are blue, uncovered lines are red.
- Add test methods that call the uncovered code. Assert on results. A test with no assertion counts for coverage but proves nothing, and we would not accept it in review.
- In the target org, validate again (Setup > Deployment Status for change sets, or the CLI below) and read the result.
How do I fix it with the CLI?
Run the tests first and print coverage per class:
sf apex run test --test-level RunLocalTests --code-coverage --result-format human -o my-sandbox
Then validate against production with the test level you will really use:
sf project deploy validate --source-dir force-app --test-level RunLocalTests -o prod
If you only want the new classes judged, name the tests:
sf project deploy start --dry-run --source-dir force-app --test-level RunSpecifiedTests --tests MyClassTest -o prod
With RunSpecifiedTests, each class in the deploy has to reach 75% on its own, which is where the 33.333% message comes from. With RunLocalTests, the org-wide average counts.
How do I stop it happening again?
Make the test class part of the same pull request as the class. Run RunLocalTests in a validate job against a full copy sandbox before the real window.
If your bundles keep arriving without tests, AI Salesforce deployments lists the covering test classes for each bundle before you approve it. For change set users, the change set errors guide has the other common failures, and the Apex glossary entry covers the basics.
Other test-time failures: assertion failed, trigger exception, validation rule in a test, callout in a test.
Questions about the 75% rule
Does the 75% rule apply to sandbox deploys?
Only when tests run. A sandbox deploy with the default test level runs no tests, so it never checks coverage. Pick RunLocalTests or RunSpecifiedTests on the validate and the sandbox enforces the same rule as production.
Do flows and Lightning components count toward the 75%?
Apex classes and triggers count. Flows have their own settings in production, covered on the flow deploy errors page.
Can I deploy a class with no tests if the org average is above 75%?
With RunLocalTests, the org-wide average is what Salesforce checks, so a high average can carry a new class. With RunSpecifiedTests, each deployed class needs 75% from the tests you named.
Why does my test pass alone and fail during the deploy?
Deploy-time runs use a clean transaction per test and no sandbox data. A test that depends on existing records, on LastViewedDate or on another test's leftovers will fail. Create everything the test needs inside the test.