You are on page 1of 27

Apex Code Testing and

Coverage Best Practices

Ryan Spraetz
Product Manager

Anand B Narasimhan
Principal Consultant
Got Twitter?
@forcedotcom / #forcewebinar

Facebook?
facebook.com/forcedotcom
Like us in the month of March and enter to win an iPod Touch
Safe Harbor
Safe harbor statement under the Private Securities Litigation Reform Act of 1995: This presentation may
contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such
uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc.
could differ materially from the results expressed or implied by the forward-looking statements we make. All
statements other than statements of historical fact could be deemed forward-looking, including any
projections of subscriber growth, earnings, revenues, or other financial items and any statements regarding
strategies or plans of management for future operations, statements of belief, any statements concerning
new, planned, or upgraded services or technology developments and customer contracts or use of our
services.

The risks and uncertainties referred to above include but are not limited to risks associated with
developing and delivering new functionality for our service, our new business model, our past operating
losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web
hosting, breach of our security measures, the immature market in which we operate, our relatively limited
operating history, our ability to expand, retain, and motivate our employees and manage our growth, new
releases of our service and successful customer deployment, and utilization and selling to larger enterprise
customers. Further information on potential factors that could affect the financial results of salesforce.com,
inc. is included in our annual report on Form 10-K filed on February 24, 2011 and in other filings with the
Securities and Exchange Commission. These documents are available on the SEC Filings section of the
Investor Information section of our Web site.

Any unreleased services or features referenced in this or other press releases or public statements are not
currently available and may not be delivered on time or at all. Customers who purchase our services should
make the purchase decisions based upon features that are currently available. Salesforce.com, inc.
assumes no obligation and does not intend to update these forward-looking statements.

P
Join the conversation on Twitter: #forcewebinar @forcedotcom
Agenda

Testing philosophy
Introduction to Apex Testing
Writing tests and test tools
Testing best practices and patterns
Testing anti-patterns
Testing Roadmap

Join the conversation on Twitter: #forcewebinar @forcedotcom


Testing Philosophy

Testing is key to successful development


Testing requirements
75% code coverage
Strive for better
Automation, automation, automation
Test suites catch regressions
Manual testing does not scale!
Apex Test Hammer
Your 8M tests are part of our release process

Join the conversation on Twitter: #forcewebinar @forcedotcom


How do I test my code?

Testmethods! How easy is that?

public class HelloDevs{ @isTest


private class TestHelloDevs{
public static String getGreeting(){
return (Test Away!); static testmethod void testGreeting(){
} String gr = HelloDevs.getGreeting();
System.assertEquals(Test Away!,gr);
static testmethod void testGreeting(){ }
String gr = HelloDevs.getGreeting(); }
System.assertEquals(Test Away!,gr);
}
}

Can only be called from test code


@isTest classes do not count towards code size limits

Join the conversation on Twitter: #forcewebinar @forcedotcom


Anatomy of a TestMethod
Demo

public class AccountProcessor{

public static Account ProcessAccount(Account acc){


//Do work here, for example:
acc.numberOfEmployees = 10;
return acc;
}

public static testmethod void testProcessAccount(){

//Create test data


Account acc = new Account(name = testAccount);

//Run the code you want to test


Test.startTest();
acc = ProcessAccount(acc);
Test.stopTest();

//Assert results
System.assertEquals(acc.numberOfEmployees, 10);

}
}

Additional Resources on Apex Test classes and Test Methods


How to Write Good Unit Tests
Apex Developer Guide

Join the conversation on Twitter: #forcewebinar @forcedotcom


Verifying my code

System.assert();
System.assertEquals();

If you are not using asserts in your test code, you are
probably not writing effective tests!

Join the conversation on Twitter: #forcewebinar @forcedotcom


Special System functions for testing

System.runAs(User){ }
Test how your code interacts with your organizations
sharing model
Does not mimic CRUD/FLS

public class TestAsUser{


public static testmethod void testAsUser(){
User u = [SELECT id FROM User LIMIT 1];
System.runAs(u){
//Code here will respect sharing model
}
}
}

Join the conversation on Twitter: #forcewebinar @forcedotcom


Special System functions for testing

Test.StartTest() and Test.StopTest()


Extra set of governor limits to test your processes

public class TestAsUser{


public static testmethod void testProcess(){
//Do data set up here
insert new Account(name = test);

//Do your testing here


Test.startTest();
ProcessAccounts();
Test.stopTest();

//Do your aserts here


System.assert()
}
}

Join the conversation on Twitter: #forcewebinar @forcedotcom


New in Spring 11!

Test.isRunningTests()
ApexOne: Fewer limits!
From over 70 individual limits to 16
Tests now get the same governor limits as regular
executions

Coming in Summer 11 at the end of the presentation


Join the conversation on Twitter: #forcewebinar @forcedotcom
Apex Testing Cookbook Recipes

Testing Http Callouts


Testing when you have a private security model
Using Test.isRunningTest

Join the conversation on Twitter: #forcewebinar @forcedotcom


Testing HTTP Callouts

Visualforce mash up to display financial transactions for an


Account
HTTP REST API to get transaction data from external
source
XML Based request/response

Join the conversation on Twitter: #forcewebinar @forcedotcom


Testing PRIVATE sharing model

Display total Opportunity Amount on an account


Displayed through an inline Visualforce page in Account detail
Rollup depends on Users profile
Hardware Product Managers should only include Hardware
opportunities
Software Product Managers should only include Software
opportunities
Account Sharing Model is PRIVATE
Opportunity Access is PRIVATE
Apex Controller runs in without sharing mode

Join the conversation on Twitter: #forcewebinar @forcedotcom


Using Test.isRunningTest

Custom Email functionality


Uses standard standard Email Templates
Uses Apex Email to send the email
Email templates presented to the end user will vary
based on users Profile
Profile specific Email Templates are stored in different folders

Join the conversation on Twitter: #forcewebinar @forcedotcom


Summary
Use Apex Object Oriented constructs to simulate
Mock Object pattern
Apex Interfaces
Apex Class Inheritance and overloading
Use Apex Manual Sharing to open up test data
records when using Private security model
Use Test.isRunningTest to execute logic specific to test
methods
Only use this as an exception (to workaround areas that are hard
to test)

Join the conversation on Twitter: #forcewebinar @forcedotcom


Apex Testing Anti Patterns
@IsTest
public class TestCoverageAntiPatterns{

public static void testmethod testButDontTest(){}


public static void testmethod testWithExistingData(){}

public static void testmethod testFakeTestCoverage(){}


}

Join the conversation on Twitter: #forcewebinar @forcedotcom


public static void testmethod testButDontTest()

Trigger to set the Close


Date of the earliest
Opportunity that is
closing on the account
whenever an
Opportunity is
updated / inserted.

Join the conversation on Twitter: #forcewebinar @forcedotcom


public static void testmethod testButDontTest()

Accounts attributes are not


validated after the Opportunity
is successfully inserted
Trigger has 75%
test coverage, and
hence can be
deployed to
production

Join the conversation on Twitter: #forcewebinar @forcedotcom


public static void testmethod testWithExistingData()

Hard coded RecordType Id. Record Types


created in Sandbox are not guaranteed to
have the same Id in production..

This Test class could fail when attempting


to deploy to a production instance.

Join the conversation on Twitter: #forcewebinar @forcedotcom


public static void testmethod testingDoneRight()

Get the Record Type Id based on the Name


of the Record Type

Assert the Account Attributes


after the opportunity is inserted
successfuly

Trigger has 100% test coverage,


and does not depend on any data
in the org

Join the conversation on Twitter: #forcewebinar @forcedotcom


public static void testmethod testFakeTestCoverage()

Join the conversation on Twitter: #forcewebinar @forcedotcom


public static void testmethod testFakeTestCoverage()

fakeXXX() methods do not perform any business


logic.

Will be able to deploy to


production without actually
testing anything.
Fake methods count
towards your Orgs
Apex limits (2MB)

Join the conversation on Twitter: #forcewebinar @forcedotcom


Apex Testing Roadmap

Asynchronous Test Execution already in pilot


Asynchronous Testing API
Test data partitioning
Ability to check org features

Join the conversation on Twitter: #forcewebinar @forcedotcom


Resources

Developer Resources
http://developer.force.com
Apex Testing Resources
How to Write Good Unit Tests
Apex Developer Guide
Apex Code Discussion Boards
Cookbook
Q&A
Get a chance to win an iPod Nano by
completing the survey at
http://bit.ly/3_30webinar

You might also like