Force.com Unit Testing Best Practice

Test classes should use the @isTest annotation

Test methods setup() creates all data needed for a method and does not rely on current data in Org
public static List<Asset> setup(Decimal assetAssetInstanceNumber, String productName)
    {
        Product2 productId = new Product2(Name=productName);
        insert productId;
        Account account = new Account(Name = '[TEST] Account ', SubscriptionStatus__c='Trial');
        insert account;

        Contact contact = new Contact(FirstName = '[TEST] FirstName ', LastName = '[TEST] Last Name ', Email='test@org.com', Phone = '12345566777',Incorporation_Type__c='Incorp Doc' , LastCompIncorpState__c='CA', AccountId =account.Id);
        insert contact;

        List<Asset> createTestAssets = new List<Asset>();
        createTestAssets.add(new Asset(Name='[TEST]', ContactId=contact.Id, AccountId=account.Id, AssetInstanceID__c=assetAssetInstanceNumber, Product2Id=productId.Id));

        Test.startTest();
            insert createTestAssets;
        Test.stopTest();
        return createTestAssets;
    }
 @isTest(SeeAllData=true) static void testContactGetsAddedToControlGroup() {
        List<Asset> getAssets = setup(1237.0,'Employee Warning Letter');

        List<CampaignMember> controlCampaignMemeber = [Select id from CampaignMember where Campaign.Name='SMB Trial Nurture Control Group' and ContactId=:getAssets[0].ContactId];
        System.assert(controlCampaignMemeber.size() == 1);
    }

Use System.assert to prove that code behaves as expected.


     Account testAccount = [select id,name from Account where Owner.Name = 'Salesforce Administrator' limit 1];
     testAccount.billingState='CA';
     Test.startTest();
     update testAccount; 
     Test.stopTest();  
     List updatedAccount = [SELECT billingState FROM Account WHERE Id = :testAccount.Id];
     System.assertEquals('CA', updatedAccount[0].billingState);
     System.assertNotEquals('NY', updatedAccount[0].billingState);
     System.assert(updatedAccount.size() == 1);

Write test methods that both pass and fail for certain conditions and test for boundary conditions.


 public static Account setupAccount()
    {
        Account testAccount = new Account(Name='[Test Account]', billingState='NY');
        insert testAccount;
        return testAccount;
    }
    @isTest static void testAccountBillingStateHasChangedToCA()
    {
        Account updatedAccount = setupAccount();
        updatedAccount.billingState='CA';
        Test.startTest();
         update updatedAccount;
        Test.stopTest();

        System.assertEquals('CA', updatedAccount.billingState);
    }
    @isTest static void testAccountBillingStateHasNotChangedToCA()
    {
        Account updatedAccount = setupAccount();
        System.assertNotEquals('CA', updatedAccount.billingState);
    }

Test triggers to process 200 records – make sure your code is “bulkified” for 200 records.

Tip: Create a variable that specified amounts of records to be created. 
After you tested no limit where reached changed amount to 1. This will speed up testing in Prod.

private static final Integer amountOfRecordsToCreate = 200;
public static List setupAccount()
    {
        List accountsToInsert = new List();
        for (int k = 0; k < amountOfRecordsToCreate;k++)
              accountsToInsert.add(new Account(Name='[Test Account]' + k, billingState='NY'));
        insert accountsToInsert;
        return accountsToInsert;
    }


If you still get the “Too many SOQL queries: 21″ exception" review
where you are making SOQL queries inside a for loop

When testing for governor limits, use Test.startTest and Test.stopTest and the Limit class instead of hard-coding governor limits.


    System.debug('Total Number of SOQL Queries allowed in this apex code context: ' +  Limits.getLimitQueries());
    System.debug('Total Number of records that can be queried  in this apex code context: ' +  Limits.getLimitDmlRows());
    System.debug('Total Number of DML statements allowed in this apex code context: ' +  Limits.getLimitDmlStatements() );
    System.debug('Total Number of script statements allowed in this apex code context: ' +  Limits.getLimitScriptStatements());
    
   //This code inefficiently queries the Opportunity object in two seperate queries
    List opptys = [select id, description, name, accountid,  closedate, stagename from Opportunity where accountId IN :Trigger.newMap.keySet()];
   
    System.debug('1.Number of Queries used in this apex code so far: ' + Limits.getQueries());
    System.debug('2.Number of rows queried in this apex code so far: ' + Limits.getDmlRows());
    System.debug('3. Number of script statements used so far : ' +  Limits.getDmlStatements());
    
    System.debug('4.Number of Queries used in this apex code so far: ' + Limits.getQueries());
    System.debug('5.Number of rows queried in this apex code so far: ' + Limits.getDmlRows());

Use System.runAs() to execute code as a specific user to test for sharing rules (but not CRUD or FLS permissions)


public class TestRunAs {
   public static testMethod void testRunAs() {
      // Setup test data
      // This code runs as the system user

         Profile p = [select id from profile where name='Standard User']; 
         User u = new User(alias = 'standt', email='standarduser@testorg.com', 
            emailencodingkey='UTF-8', lastname='Testing', languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, 
            timezonesidkey='America/Los_Angeles', username='standarduser@testorg.com');


         System.runAs(u) {
           // The following code runs as user 'u' 
           System.debug('Current User: ' + UserInfo.getUserName());
           System.debug('Current Profile: ' + UserInfo.getProfileId()); }
           // Run some code that checks record sharing
        }
}

Use Salesforce SmartFactory to help setup Test Records.

https://github.com/thysmichels/SmartFactory-for-Force.com


Account account = (Account)SmartFactory.createSObject('Account');
Contact contact = (Contact)SmartFactory.createSObject('Contact', true);
Custom_Object__c customObject = (Custom_Object__c)SmartFactory.createSObject('Custom_Object__c');
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: