Diagnosing tricky edge cases and preventing regressions requires more than adding temporary System.debug() lines. Salesforce arms developers with two essential diagnostic tools: Checkpoints (detailed heap inspection during execution) and the modern Assert class (programmatic condition validation in unit tests and business logic). Mastering both helps you validate architectural assumptions and debug complex codebases faster.
1. Understanding Developer Console Checkpoints
Unlike standard breakpoints that simply pause execution, a Checkpoint captures a detailed snapshot of memory at a precise line of execution. When your transaction reaches that checkpoint line, Salesforce records execution metrics and in-memory variables into a dedicated checkpoint result.
- Heap Dump Inspection: View every active variable, collection, and instantiated sObject in memory at that exact moment.
- Symbols and Action Scripts: Run diagnostic SOQL queries or execute Apex code against the exact memory state captured at the checkpoint.
- Execution Stack Tracking: Trace method calls and investigate call-stack depth across triggers, handler classes, and service layers.
- Open the Developer Console in your Salesforce org.
- Open your Apex class or Trigger and navigate to the target line of code.
- Click to the left of the line number in the code editor margin (or place your cursor and press
Ctrl + Shift + B/Cmd + Shift + B) to place a checkpoint indicator. - Execute the code via an Anonymous Apex script, unit test, or UI user action.
- Open the Checkpoints tab in the bottom panel and double-click the captured result to explore the Heap Dump and Symbols Tree.
2. Modern Apex Assertions: The Assert Class
Assertions validate that code outputs match architectural expectations. While legacy Apex used System.assert(), modern Salesforce development standardizes on the fluent Assert namespace class, offering improved readability, built-in exception types, and self-documenting method signatures.
Assert.areEqual(expected, actual, msg): Validates that two values match, replacingSystem.assertEquals().Assert.areNotEqual(notExpected, actual, msg): Confirms that two values are distinct.Assert.isTrue(condition, msg)&Assert.isFalse(condition, msg): Validates Boolean logic flags and business rule outcomes.Assert.isNull(value, msg)&Assert.isNotNull(value, msg): Confirms object instantiation and query returns.Assert.fail(msg): Instantly fails a test path (useful when testing negative scenarios inside catch blocks).
Verifying that a service layer class properly applies tiered account discounts:
@IsTest
private class AccountDiscountServiceTest {
@IsTest
static void testApplyTierOneDiscount() {
// Arrange
Account testAcc = new Account(Name = 'Acme Enterprise', AnnualRevenue = 2000000);
insert testAcc;
// Act
Test.startTest();
Decimal calculatedDiscount = AccountDiscountService.getDiscountRate(testAcc.Id);
Test.stopTest();
// Assert using modern Apex Assert class
Assert.isNotNull(calculatedDiscount, 'Discount rate should not return null');
Assert.areEqual(0.15, calculatedDiscount, 'Enterprise accounts must receive a 15% discount rate');
}
}
- Checkpoints: Investigative tool used during development to inspect in-memory heap structures without changing code.
- Assertions: Automated testing statements embedded in test classes to safeguard logic against regressions.
- Max Active Checkpoints: Salesforce allows up to 5 active checkpoints simultaneously per org.
- Checkpoint Expiration: Captured checkpoint allocations clear when the Developer Console session ends or expires after 30 minutes of inactivity.
3. Common Traps & Best Practices
Setting more than 5 checkpoints will cause new checkpoints to be ignored without warning. In addition, writing unit tests without assertion statements to inflate code coverage gives a false sense of security; tests without assertions verify execution, not correctness.
System.assert statements with the modern, strongly typed Assert class.
- Include Descriptive Failure Messages: Always supply the optional message parameter in assertions (e.g.,
Assert.isTrue(isProcessed, 'Record should be processed')) so failed test runs identify the exact business failure immediately. - Clear Unused Checkpoints: Regularly clear completed checkpoints in the Developer Console's Checkpoints Manager tab to avoid hit limits on capture slots.
- Pair with Granular Debug Logs: When troubleshooting complex integration failures, pair checkpoints with customized User Trace Flags set to
FINEorDEBUGfor end-to-end visibility.
Summary
Checkpoints and assertions form the backbone of reliable Salesforce debugging and automated testing. By capturing in-memory snapshots with checkpoints and validating business assumptions with the Apex Assert class, you can isolate runtime bugs quickly and build resilient, production-ready Salesforce applications.