Salesforce testing is the foundation of reliable Apex development and successful production deployments. Whether you’re building triggers, classes, or custom applications, proper testing ensures your code handles both single records and bulk operations while meeting Salesforce’s 75% code coverage requirement for production deployment.
This guide covers everything from basic unit testing concepts to advanced performance testing strategies, helping you build robust Salesforce applications that scale in enterprise environments.
What is Salesforce Testing?
Salesforce testing validates that your Apex code works as expected across different scenarios and data volumes. Testing is mandatory for production deployments and critical for long-term application stability.
There are two primary approaches to testing Salesforce applications:
- Manual testing through Salesforce UI – Testing with single records through the standard interface
- Automated testing with bulk data – Testing functionality with up to 200 records using Apex test classes and data loader operations
Production Deployment Requirements
Before deploying code to production, Salesforce enforces these mandatory requirements:
- 75% of Apex code must be covered by unit tests
- All test methods must complete successfully
- Tests must cover positive scenarios, negative scenarios, and bulk operations
- System.debug() statements do not count toward code coverage
Important: Focus on comprehensive test coverage rather than just meeting the 75% threshold. Your tests should validate every use case, including edge cases and error conditions.
Best Testing Approach for Salesforce
Salesforce.com recommends testing these five critical components:
1. Single Record Testing
Verify that individual records produce correct, expected results. This includes testing trigger logic, validation rules, and workflow automation for single record operations.
@isTest
private class AccountTriggerTest {
@isTest
static void testSingleAccountCreation() {
// Test single record scenario
Account testAccount = new Account(
Name = 'Test Account',
Industry = 'Technology'
);
Test.startTest();
insert testAccount;
Test.stopTest();
// Verify expected behavior
Account insertedAccount = [SELECT Id, Name, Industry FROM Account WHERE Id = :testAccount.Id];
System.assertEquals('Test Account', insertedAccount.Name);
}
}
2. Bulk Record Testing
Test your code with multiple records (up to 200 in test context) to ensure proper bulkification and governor limit compliance.
@isTest
static void testBulkAccountCreation() {
List testAccounts = new List();
// Create 200 test records
for(Integer i = 0; i < 200; i++) {
testAccounts.add(new Account(
Name = 'Bulk Test Account ' + i,
Industry = 'Technology'
));
}
Test.startTest();
insert testAccounts;
Test.stopTest();
// Verify bulk operation results
List insertedAccounts = [SELECT Id FROM Account WHERE Name LIKE 'Bulk Test Account%'];
System.assertEquals(200, insertedAccounts.size());
}
3. Positive and Negative Scenario Testing
Positive scenarios test expected successful operations, while negative scenarios verify proper error handling and validation.
@isTest
static void testNegativeScenario() {
Account testAccount = new Account(); // Missing required Name field
Test.startTest();
try {
insert testAccount;
System.assert(false, 'Expected DML exception was not thrown');
} catch(DmlException e) {
System.assert(e.getMessage().contains('REQUIRED_FIELD_MISSING'));
}
Test.stopTest();
}
4. Restricted User Testing
Verify that users with limited permissions see appropriate behavior, whether successful execution or proper error messages.
@isTest
static void testRestrictedUserAccess() {
// Create user with limited permissions
User restrictedUser = TestDataFactory.createRestrictedUser();
System.runAs(restrictedUser) {
Test.startTest();
try {
Account testAccount = new Account(Name = 'Restricted Test');
insert testAccount;
} catch(DmlException e) {
System.assert(e.getMessage().contains('INSUFFICIENT_ACCESS'));
}
Test.stopTest();
}
}
Types of Testing in Salesforce
Unit Testing
Unit testing validates individual components (methods, triggers, classes) in isolation. This is the developer’s primary responsibility and forms the foundation of your test strategy.
Best practices for unit testing:
- Test one method or functionality per test method
- Use descriptive test method names that explain the scenario
- Create test data within each test method or use @testSetup
- Assert expected outcomes explicitly
- Test both success and failure paths
Integration Testing
Integration testing validates how multiple components work together, such as triggers interacting with workflow rules, or custom classes calling other classes.
@isTest
static void testTriggerWorkflowIntegration() {
// Test how trigger logic integrates with workflow rules
Account testAccount = new Account(
Name = 'Integration Test',
Industry = 'Healthcare',
AnnualRevenue = 1000000
);
Test.startTest();
insert testAccount;
Test.stopTest();
// Verify both trigger and workflow executed correctly
Account updatedAccount = [SELECT Id, Rating, Description FROM Account WHERE Id = :testAccount.Id];
System.assertEquals('Hot', updatedAccount.Rating); // Set by trigger
System.assertNotEquals(null, updatedAccount.Description); // Set by workflow
}
System Testing
System testing validates the complete application flow from end-to-end, including user interface interactions, data processing, and integrations.
Salesforce Performance Testing Tools
Performance testing ensures your Salesforce applications handle expected load and scale appropriately in production environments.
Native Salesforce Testing Tools
Test.startTest() and Test.stopTest() – Resets governor limits and enables testing of asynchronous operations:
@isTest
static void testAsyncProcessing() {
Test.startTest();
// Governor limits reset here
MyBatchClass batch = new MyBatchClass();
Database.executeBatch(batch, 200);
Test.stopTest(); // Forces batch to complete
// Verify batch processing results
List processedAccounts = [SELECT Id FROM Account WHERE Processed__c = true];
System.assert(processedAccounts.size() > 0);
}
Limits class – Monitor resource consumption during tests:
@isTest
static void testGovernorLimits() {
System.debug('SOQL queries before: ' + Limits.getQueries());
System.debug('DML statements before: ' + Limits.getDMLStatements());
Test.startTest();
// Execute your code
MyClass.processRecords();
Test.stopTest();
System.debug('SOQL queries after: ' + Limits.getQueries());
System.debug('DML statements after: ' + Limits.getDMLStatements());
// Assert limits are within acceptable ranges
System.assert(Limits.getQueries() < 50, 'Too many SOQL queries executed');
}
Third-Party Performance Testing Tools
- JMeter with Salesforce plugins – Load testing for REST API endpoints
- Selenium WebDriver – UI automation and performance testing
- Postman/Newman – API testing and monitoring
- Salesforce CLI performance commands – Deployment and metadata performance analysis
Advanced Testing Strategies
Test Data Management
Use @testSetup to create shared test data efficiently:
@testSetup
static void setupTestData() {
List testAccounts = new List();
for(Integer i = 0; i < 10; i++) {
testAccounts.add(new Account(
Name = 'Test Account ' + i,
Industry = 'Technology'
));
}
insert testAccounts;
}
Mock Testing for External Integrations
Use HttpCalloutMock to test external service integrations:
@isTest
global class MockHttpResponseGenerator implements HttpCalloutMock {
global HTTPResponse respond(HTTPRequest req) {
HttpResponse res = new HttpResponse();
res.setHeader('Content-Type', 'application/json');
res.setBody('{"status":"success"}');
res.setStatusCode(200);
return res;
}
}
@isTest
static void testExternalCallout() {
Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());
Test.startTest();
String response = MyIntegrationClass.callExternalService();
Test.stopTest();
System.assertEquals('success', response);
}
Common Testing Pitfalls and Solutions
Governor Limit Violations
Problem: Tests fail due to SOQL query limits or DML statement limits.
Solution: Implement proper bulkification patterns and use Test.startTest() to reset limits.
Hard-Coded IDs
Problem: Tests break when deployed to different environments.
Solution: Query for records dynamically or use custom settings for configuration.
Insufficient Negative Testing
Problem: Code fails in production due to unexpected error conditions.
Solution: Test validation rules, required fields, and permission restrictions explicitly.
Testing Best Practices for Enterprise Orgs
- Separate test classes by functionality – One test class per trigger or major class
- Use meaningful assertions – Assert specific values, not just “not null”
- Test with realistic data volumes – Use bulk testing patterns consistently
- Implement continuous integration – Automate test execution with deployment pipelines
- Monitor test performance – Track test execution time and optimize slow tests
- Document test scenarios – Maintain clear test documentation for complex business logic
Deployment Testing Checklist
Before deploying to production, verify:
- All test classes execute successfully in target environment
- Code coverage meets or exceeds 75% requirement
- No hard-coded IDs or environment-specific references
- External service mocks are properly configured
- User permission scenarios are tested
- Bulk data scenarios are validated
- Error handling paths are covered
Frequently Asked Questions
What is the minimum code coverage required for Salesforce testing?
Salesforce requires 75% code coverage for production deployments. However, focus on comprehensive test scenarios rather than just meeting the percentage threshold. Your tests should cover positive cases, negative cases, bulk operations, and edge conditions.
Do I need test classes when deploying from sandbox to sandbox?
No, Salesforce does not require code coverage when deploying between sandbox environments. However, it’s still a best practice to run your tests to ensure functionality works correctly in the target environment.
How do I test bulk operations in Salesforce?
Create test methods that process multiple records (up to 200 in test context). Use List collections to create bulk test data, then verify your code handles the volume without hitting governor limits. Always use Test.startTest() and Test.stopTest() to reset limits during bulk testing.
What are the best testing approach for Salesforce integrations?
Use HttpCalloutMock interfaces to simulate external service responses. Test both successful responses and error conditions. Create separate test methods for different response scenarios (success, timeout, server error) to ensure your integration handles all cases gracefully.
How do I test restricted user scenarios in Salesforce?
Use System.runAs() to execute code as users with different permission sets. Create test users with specific profiles and permission sets, then verify your code either executes successfully or throws appropriate security exceptions based on the user’s access level.
Which salesforce performance testing tools should I use?
Start with native Salesforce tools like Test.startTest(), Test.stopTest(), and the Limits class for basic performance testing. For advanced scenarios, use JMeter for API load testing, Selenium for UI performance testing, and Salesforce CLI for deployment performance analysis.