Apex Unit Testing in the Real World
-
Upload
salesforce-developers -
Category
Documents
-
view
691 -
download
0
Transcript of Apex Unit Testing in the Real World
Apex Unit Testing in the Real World
Dan Appleman, Full Circle CRM, CTO
Author: “Advanced Apex Programming for Salesforce.com and Force.com”
@danappleman
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
product or service availability, 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, new products and services, 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 outcome of intellectual property and other l itigation, risks associated
with possible mergers and acquisitions, 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, our limited history reselling
non-salesforce.com products, 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-Q for the most recent fiscal quarter ended July 31, 2012. This
documents and others containing important disclosures 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 presentations, 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.
Recommended Testing Best Practices
Single action
Test to verify that a single record produces the correct, expected result.
Bulk actions
Any Apex code, whether a trigger, a class or an extension, may be invoked for 1 to 200 records. You must test not only
the single record case, but the bulk cases as well.
Positive behavior
Test to verify that the expected behavior occurs through every expected permutation, that is, that the user filled out
everything correctly and did not go past the limits.
Negative behavior
There are likely limits to your applications, such as not being able to add a future date, not being able to specify a
negative amount, and so on. You must test for the negative case and verify that the error messages are correctly
produced as well as for the positive, within the limits cases.
Restricted user
Test whether a user with restricted access to the sObjects used in your code sees the expected behavior. That is,
whether they can run the code or receive error messages.
Why don’t we do it?
Consultants?
In-house Developers?
Package Developers?
Let’s Play a Game
20,000 Fictional Apex Developers were asked – why write
unit tests?
20,000 Fictional Apex Developers were asked – why write
unit tests?
20,000 Fictional Apex Developers were asked – why write
unit tests?
20,000 Fictional Apex Developers were asked – why write
unit tests?
20,000 Fictional Apex Developers were asked – why write
unit tests?
20,000 Fictional Apex Developers were asked – why write
unit tests?
20,000 Fictional Apex Developers were asked – why write
unit tests?
Testing to Requirements
1. Forces you to actually define requirements
2. Validates that what you built meets requirements
3. “Free” regression testing
4. “Free” target compatibility
5. May even get you code coverage.
All Testing is Bulk Testing - I
Bad code
public static testmethod void test1bad()
{
Lead ld = new Lead(LastName='Testname',
Company='Testcompany');
Test.StartTest();
insert ld;
Test.StopTest();
Lead leadres = [Select ID from Lead where
ID = :ld.id];
// Do some assert here
}
All Testing is Bulk Testing - II
Better code
public static testmethod void test1better()
{
List<Lead> lds = new List<Lead>{
new Lead(LastName='Testname',
Company='Testcompany')};
Test.StartTest();
insert lds;
Test.StopTest();
Map<ID, Lead> leadsmap = new Map<ID, Lead>(lds);
List<Lead> leadres = [Select ID from Lead where
ID in :leadsmap.keyset()];
// Do some asserts here
}
All Testing is Bulk Testing - III
Centralize object initialization
public static List<Lead> InitTestLeads(
Integer count)
{
List<Lead> lds = new List<Lead>();
for(Integer x = 0; x< count; x++)
{
lds.add(new Lead(LastName='Testname' +
String.ValueOf(x), Company='Testcompany' +
String.ValueOf(x)));
}
return lds;
}
All Testing is Bulk Testing - IV
Pull test code into a separate method
public static void test2support(Integer batchsize)
{
List<Lead> lds = InitTestLeads(batchsize);
Test.StartTest();
insert lds;
Test.StopTest();
Map<ID, Lead> leadsmap = new Map<ID, Lead>(lds);
List<Lead> leadres = [Select ID from Lead where
ID in :leadsmap.keyset()];
// Do some asserts here
}
All Testing is Bulk Testing – Oh yeah!
And let the magic happen
@istest(oninstall=true)
public static void test2single()
{
Test2Support(1);
}
@istest(oninstall=false)
public static void test2bulk()
{
Test2Support(200);
}
Results:
Direct functional/requirements validation
Free regression testing
Free target compatibility
Cheap bulk testing
Lower maintenance costs
Most code coverage met
Bonus for Package Developers
You can block tests using oninstall=false, but still need 75%
code coverage to install.
How do you shut down individual tests?
How do you initialize object fields to address validation rules on
a target system?
How do you customize behavior during install while maintaining
a single code base?
Static Resources to the Rescue
Static Resource Centralized object
Initialization function
Field initialization info
Test function
Allow test to run?
Control test
execution
Other code
(test or functional)
Control behavior
resources = [Select Body from StaticResource where Name = ‘predeployedresource' ];
Conclusion
You can’t (and shouldn’t) ignore the economics of testing.
Making general testing goals a priority over code coverage is the
sound economic choice.
Next Steps
Question for chatter – tell us about a testing
challenge you overcame.
Stop by and chat at the Full Circle CRM booth
btw… we’re hiring
www.AdvancedApex.com
No question? – Tell us about your favorite testing technique.
AdvancedApex.com