25
Apex Unit Testing in the Real World Dan Appleman, Full Circle CRM, CTO Author: “Advanced Apex Programming for Salesforce.com and Force.com” @danappleman

Apex Unit Testing in the Real World

Embed Size (px)

Citation preview

Page 1: 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

Page 2: Apex Unit Testing in the Real World

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.

Page 3: Apex Unit Testing in the Real World

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.

Page 4: Apex Unit Testing in the Real World

Why don’t we do it?

Consultants?

In-house Developers?

Package Developers?

Page 5: Apex Unit Testing in the Real World

Let’s Play a Game

Page 6: Apex Unit Testing in the Real World

20,000 Fictional Apex Developers were asked – why write

unit tests?

Page 7: Apex Unit Testing in the Real World

20,000 Fictional Apex Developers were asked – why write

unit tests?

Page 8: Apex Unit Testing in the Real World

20,000 Fictional Apex Developers were asked – why write

unit tests?

Page 9: Apex Unit Testing in the Real World

20,000 Fictional Apex Developers were asked – why write

unit tests?

Page 10: Apex Unit Testing in the Real World

20,000 Fictional Apex Developers were asked – why write

unit tests?

Page 11: Apex Unit Testing in the Real World

20,000 Fictional Apex Developers were asked – why write

unit tests?

Page 12: Apex Unit Testing in the Real World

20,000 Fictional Apex Developers were asked – why write

unit tests?

Page 13: Apex Unit Testing in the Real World

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.

Page 14: Apex Unit Testing in the Real World

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

}

Page 15: Apex Unit Testing in the Real World

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

}

Page 16: Apex Unit Testing in the Real World

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;

}

Page 17: Apex Unit Testing in the Real World

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

}

Page 18: Apex Unit Testing in the Real World

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);

}

Page 19: Apex Unit Testing in the Real World

Results:

Direct functional/requirements validation

Free regression testing

Free target compatibility

Cheap bulk testing

Lower maintenance costs

Most code coverage met

Page 20: Apex Unit Testing in the Real World

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?

Page 21: Apex Unit Testing in the Real World

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' ];

Page 22: Apex Unit Testing in the Real World

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.

Page 23: Apex Unit Testing in the Real World

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

Page 24: Apex Unit Testing in the Real World

No question? – Tell us about your favorite testing technique.

Page 25: Apex Unit Testing in the Real World

AdvancedApex.com