If you've ever tried to push Apex code to a production org, you've met Salesforce's deployment gatekeeper: the mandatory test run. In 2026, those rules haven't relaxed at all — and that's deliberate. Tests aren't bureaucracy; they're how a shared, multi-tenant platform stays trustworthy when thousands of developers ship code every day.

Why Salesforce enforces test coverage

Salesforce executes your code alongside everyone else's in a multi-tenant architecture. A careless trigger on your org can't be allowed to undermine the platform's reliability for your users. Mandatory tests serve two purposes:

  1. Deployment safety. Production deployments require a passing test run. If your tests fail, your metadata stays in the sandbox. Simple as that.
  2. Regression insurance. Orgs evolve constantly — admins add flows, validation rules, and required fields. A solid test suite catches the breakage before your users do.

The coverage rules, precisely

Here is what the platform actually demands before a production deployment:

  • At least 75% of all Apex code in the org must be executed by tests.
  • Every trigger must have some coverage — an untested trigger blocks deployment even if the org-wide number looks fine.
  • All test methods must pass. No failures, no uncaught exceptions.
  • Test classes themselves don't count toward the 75%.

Notice what's missing from that list: any requirement that your tests be good. A test that executes code without asserting anything still inflates the percentage. Which brings us to the real problem.

Stop gaming coverage; start asserting

Coverage is a floor, not a finish line. A test without System.assert calls proves nothing except that your code doesn't crash on one narrow path. Meaningful tests assert outcomes:

  • Assert the business result, not the implementation detail. ("The opportunity moved to Closed Won" beats "the method returned true.")
  • Test the unhappy paths: validation failures, null inputs, and governor-limit-adjacent bulk sizes.
  • Cover every branch of your conditionals — both sides of each if/else and every ternary outcome.

Write tests you'd trust to run at 2 AM during a release window. We walk through the full setup in our test classes and code coverage guide.

Bulk-safe test data patterns

Tests that insert a single record and call it a day are lying to you. Real orgs process data in bulk — triggers fire on up to 200 records at a time. Build that reality into your tests from the start:

  • Create your own data. Never depend on existing org data (SeeAllData=true is a trap that makes tests fail in fresh sandboxes). Generate records that mirror real business scenarios, including related records.
  • Use @TestSetup. One setup method builds shared data once per test class, keeping tests fast and consistent.
  • Centralize with a Test Data Factory. A single utility class that produces Accounts, Contacts, and Opportunities with sensible defaults saves everyone on the team from reinventing fixtures.
  • Test in bulk. Insert 200 records, not one. That's where SOQL-in-loop bugs and governor-limit failures hide.
@isTest private class AccountTriggerTest { @TestSetup static void makeData() { List<Account> accts = new List<Account>(); for (Integer i = 0; i < 200; i++) { accts.add(new Account(Name = 'Test ' + i)); } insert accts; } @isTest static void bulkInsertSetsIndustry() { Test.startTest(); // trigger logic under test runs against the @TestSetup data Test.stopTest(); Integer flagged = [SELECT COUNT() FROM Account WHERE Industry = 'Technology']; System.assertEquals(200, flagged, 'All bulk-inserted accounts should be flagged'); } } 

Test.startTest() and Test.stopTest() also reset governor limits and force asynchronous code — future methods, queueables, batch jobs — to run synchronously, which is essential for testing anything @future or scheduled.

Deployment gotchas that still bite in 2026

  • Coverage evaporates on edit. The moment you modify a class, its coverage data is cleared until tests run again. Re-run after every change.
  • Mixed DML errors. Creating a User and an Account in the same transaction blows up. Wrap user-context setup in System.runAs(), which also lets you verify sharing rules and profile behavior.
  • Run test classes individually when debugging. One class at a time makes failures far easier to isolate than a full-org run.
  • Aim above the minimum. 75% gets you deployed; targeting 90% or more across classes and triggers gives you headroom for the inevitable coverage dip when someone edits a class the night before a release.

Good tests are documentation that executes. They tell the next developer what the code is supposed to do — and they scream when it stops doing it. Write them like the next person reading them is you, six months from now, during an incident.

Originally published at Way2Force.