Back to insights

Testing & DevOps

Code coverage is not a Salesforce testing strategy

JSBC Labs8 min read

A deployment gate is not evidence of quality

Salesforce requires at least 75% Apex code coverage for production deployment. That rule is useful because it prevents completely untested code from entering an org, but it is a weak target for an engineering team. Coverage proves that a test caused a line to execute. It does not prove that the test asserted the correct outcome, exercised the dangerous branch or protected the customer journey that pays for the platform.

A test can execute every line in a method and still miss an incorrect permission decision, a duplicate integration message or a bulk update that fails at record 201. When teams optimise for the percentage, they naturally write tests that satisfy the deployment mechanism. When they optimise for operational risk, they write tests that explain what the system must continue to do. Those are very different assets.

Begin with behaviours and failure costs

The useful unit of testing is a business behaviour: a qualified lead is routed to the correct team; a closed opportunity creates one order; an unauthorised user cannot see a sensitive field; a retried event does not create a duplicate case. Each behaviour has a success condition, a failure condition and a consequence if it breaks. That consequence should determine how deeply and how often it is tested.

Create a small risk map for every change. Ask which users and records are affected, whether money or regulated data is involved, whether the change crosses a system boundary and how easily it can be reversed. Low-risk presentation changes may need focused component checks. Security, data model, automation and integration changes need broader regression coverage. Salesforce Well-Architected explicitly recommends different testing regimes for different levels of change risk rather than forcing every release through the same undifferentiated checklist.

Tests should own their data

Reliable Apex tests create the records they need and remain isolated from the current contents of the org. Salesforce restricts access to organisation data in tests by default, and that is an architectural advantage. A test that passes only because a particular Account, Profile name or custom setting exists in one sandbox is not a repeatable test; it is an undocumented dependency.

Use test-data factories to express valid defaults, then override only the fields relevant to the scenario. Include boundary data deliberately: nulls, malformed values, maximum lengths, duplicates, large collections and records owned by users with different access. The factory should make tests easier to read, not generate an entire artificial enterprise for every method. Small, intentional datasets produce faster failures and make the reason for each assertion visible.

Test the boundaries where systems usually break

Most expensive Salesforce failures occur between components rather than inside one method. A Flow invokes Apex, Apex publishes an event, a subscriber calls an external service and a later transaction updates the originating record. Unit tests for each component are necessary, but they do not prove that the contract between them is coherent.

For each boundary, test the payload, identity, permissions, transaction behaviour and retry rule. Use mocks and stubs for callouts so that success, timeout, malformed response and business rejection can all be reproduced. Verify idempotency by processing the same message twice. Verify partial failure in bulk operations. Verify that an asynchronous failure leaves enough durable context for an operator to recover it. The happy path confirms that the feature can work; these tests confirm that the service can be operated.

Declarative automation belongs in the same strategy

Apex is not the only production logic in an org. Record-triggered flows, validation rules, duplicate rules, assignment rules and permission configuration can change the outcome of the same transaction. An Apex suite may pass while the complete process fails because a Flow was reordered or a new validation rule rejects the test setup used by an integration.

Salesforce provides integrated testing for supported Flow types, and teams should use it for important declarative paths. Beyond individual Flow tests, maintain a small set of end-to-end regression scenarios that traverse the real combination of automation. Execute them under representative user permissions, not only as an administrator. A system that works in elevated context but fails for the service agent is not release-ready.

Build a pipeline that returns useful evidence

Run fast unit tests on every proposed change and reserve broader suites for the risk they address. A practical pipeline might progress from static checks and focused Apex or Flow tests, to object-level regression, integration-contract tests, user-journey checks and finally performance or scale testing for high-risk releases. Salesforce notes that meaningful scale testing requires production-like workload characteristics and, for true platform scale testing, an appropriate Full sandbox.

Do not reduce the result to a green tick. Track which business capabilities are protected, which tests are unreliable, how long feedback takes and what escaped into production. A flaky test is not harmless noise: it trains teams to ignore failure. A slow suite encourages bypasses. A strong pipeline makes the safest route to production the easiest route to follow.

The JSBC Labs view

Keep coverage above the Salesforce minimum, but stop treating the number as the objective. The real test strategy is a map between business risk and executable evidence. It includes code, configuration, security, data, integrations and the workloads the platform will actually receive.

Start with the ten business behaviours the organisation could least afford to break. Give each one a clear owner, representative data, positive and negative scenarios, and a place in the release pipeline. That small shift turns testing from a deployment tax into something far more valuable: a controlled way to change Salesforce without repeatedly rediscovering the same risks in production.

Official references

Continue reading