Salesforce Testing: Complete Guide | SalesforceTutorial

Written by Prasanth Kumar Published on Updated on

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:

  1. Manual testing through Salesforce UI – Testing with single records through the standard interface
  2. 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.