Preface – This post is part of the Write Your First Intermediate Trigger series.
To get the minimum required 75% test coverage, all you have to do is make Salesforce run the code that you want to test. So if you have a “before insert” trigger on Contacts, simply creating a new Contact in your test class will get you your code coverage!
In the beginning, it might seem sufficient just to get enough code coverage to deploy your code. Experienced developers however will always take a few extra steps to also make sure their code is rock solid too.
If you’re planning to get a job as a Salesforce developer one day, these testing principles are an absolute must learn!
Salesforce Apex Testing Best Practices:
1. Create all records in your test from scratch: Assume you’ll be deploying your code in an org that has no records!
Why? If any records in your production org get deleted or changed, there’s no chance your test class fails since it builds its own records!
Best Practice #1: Create records from scratch!
2. Use System.assertEquals() to see if your code has the expected outcomes: for example, if your code changes a Contact’s status to ‘Single’, make sure it actually did by doing System.assertEquals(‘Single’, myContact.Status__c);
Why? Just because you get full code coverage, doesn’t mean your code actually works!
Best Practice #2: Be “assert”-ive!
3. Test for scenarios that shouldn’t work: Let’s say in our previous example that we changed our Contact’s status to ‘Single’ only if he lost his job as a Salesforce developer. We’d also want to test this scenario using System.assertEquals(‘In a Relationship’, myContact.Status__c);
Why? This tests to see if our code does things it shouldn’t do! This is called negative testing, and it makes sure we evaluate our code 360 degrees.
Best Practice #3: Break things!
4. Test in bulk: Test to see if your code can run on 200 records at once. This is the maximum number of records that can be evaluated in a single trigger by Salesforce.
Don’t worry about this one too much for now, since we’ll be talking more about it in our Governor Limits chapter! It’s possible that your code runs fine if a single Contact goes through your trigger – but it might break if 200 Contacts are evaluated in your trigger!
Best Practice #4: Be “bulky”
That’s almost 200 pounds, just like the maximum batch size in Salesforce!
We’ll apply these principles (with specific examples) when we create the test class for our deduping trigger!
Next post: We write a test class for our deduping trigger!
I cannot express how helpful this has been for me in my Salesforce Developer Journey. I am currently an admin looking to step into the dev side as well. Thank you for all of this information.
=)
HI David!
First I wanted to say Thank-you (like everyone else who has come across this gold mine)! Its truly appreciated how much you are doing for the community of beginners in the Salesforce universe.
Now am struggling on salesforce beginng not sure about Best Practice #1. would you explain more to me please
Hello David,
I am beginner. I have written a Trigger which auto populates the Description field on contact when a new contact is created. Trigger is working good. But my test class is failing. Please can you point out where I am going wrong.
/** Trigger**/
trigger ContactDescription on Contact (before insert ,before update) {
for(contact myContact : Trigger.new)
{
if(Trigger.isInsert && myContact.Description==NULL)
{
myContact.Description=’Contact Description updated by Contact description trigger’;
}
if(Trigger.IsUpdate)
{
myContact.Description=’Contact Description updated successfully by ‘+userinfo.getFirstName();
}
}
}
/** TEST CLASS**/
@iSTest
public class TestContactDescription {
static testmethod Void ContactDescriptionTest()
{
contact mytestContact =new contact();
mytestContact.LastName=’Wangdo’;
mytestContact.FirstName=’Phunsukh’;
insert myTestContact;
system.debug(‘new contact inserted ‘+myTestContact.FirstName+’ ‘+MyTestContact.LastName);
//system.assertEquals(‘Contact Description updated by Contact description trigger’,MyTestContact.Description);
system.debug(‘Description updated by trigger’);
myTestContact.Description=’Not updated from the trigger’;
update myTestContact;
//system.assertNotEquals(‘Contact Description updated by Contact description trigger’,MyTestContact.Description);
system.debug(‘Description not updated by trigger’);
listcontactList=new list();
for(Integer i=0;i<200;i++)
{
contact contact_trig=new contact();
contact_trig.LastName='Trigger ' + i;
contactList.add(contact_trig);
}
insert contactList;
system.debug('No of contacts inserted is '+contactList.size());
}
}
/**ERROR**/
assertion failed
Try asking the official developer forums!
There is an error in contact list which is from below to 11th line. Everything is good. It will give 100% code coverage..
Thank you again, David, for this awesome website… I was 4/6 on Code Coverage and I only followed the first rule which is to create all records from scratch in my test class, and now it’s 6/6 100%!!!
Before I deploy the below into our business org next week, I have noticed that this new trigger I have built will only apply to records that are being edited. Is there anyway I can apply the trigger to my entire org without having users to make edits or having us to use dataloader to load the current data into the existing records?
trigger primaryLiaisonCount2 on Contact(after update, before update) {
//c1 each Contact that goes through the trigger
for (Contact c1: trigger.new){
//amount1 = Amount of Primary Liaisons in each Accounts
decimal amount1=[SELECT count() FROM Contact WHERE AccountID =:c1.AccountID AND Primary_Liaison__c != null];
LIST acc1=[SELECT ID FROM Account WHERE recordtypeID =’012000000000j8S’];
for (Account acc2:acc1){
acc2.Primary_Liaisons__c = amount1;
upsert acc2;
}
Loved the sense of humor in this article David!
Hi btw. I have been just thrown into this Apex programming by my boss, when I had never worked on it before. But Apex and SalesForce seems interesting enough for me to delve deeper into learning it. And it’s then that I stumbled on your site sfdc99.
And I think this is my last stumble since your site seems pretty much the pi stop for anything related to Apex! Wonderful articles. I would be following your articles henceforth. Keep up the good work. :)
Thank you!
As said I am still following your site and other resources. I even checked out the webinar videos at https://developer.salesforce.com/en/events/webinars/apex-for-admins-beyond-the-basics?d=70130000000lhDO.
But it doesn’t seem to help me getting out of my troubles. And I hope you can help me here.
Thanks to your tutorials I can write Triggers and make a test class with “best practices”. So technically I think I won’t have a problem now. But I still can’t understand the basic concepts of “Leads”, “Accounts”, “Contacts”, “Tasks” etc… I did know the individual concepts, but I am having trouble establishing relationships between these objects.
I was not able to find a comprehensive guide which explains the concepts of these objects in some detail (not the technical side). Also is there some ER diagram to understand the relationship between these objects?
I am not sure about Best Practice #1. would you explain more to me please ?
Your test needs to run on a totally independent database (but same schema) – so you need to create the database records from scratch!
HI David!
First I wanted to say Thank-you (like everyone else who has come across this gold mine)! Its truly appreciated how much you are doing for the community of beginners in the Salesforce universe.
Now I get needy! I’m really struggling with a unit test for a VF controller. I’ve hacked my way through fullcalendar.js to get it to behave the way I need to (in my dev sandbox). But I can’t for the life of me wrap my head around the logic of what, or how, to test the controller. Even after reading through developer.force.com documents on the subject! Is there any way that you’d be able to help.
I’ll save the rest of the details, but, if you think you can assist, I’ll share with you :)
Either way, keep up the fantastic work on this site.
Testing controllers actually isn’t that bad! Setting it up is a little weird but afterwards all you do is call its methods one by one and you’ll be done in no time!
I basically followed this template when writing my first test class for controllers:
http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_error_handling.htm
Actually the next chapter covers this kind of stuff (classes!) but I’ll try to explain briefly. Your controller is simply a folder of methods. So your test needs to open this folder and call each method. For example, if a user would click the custom “Save” button, in your test class you do myController.customSave(); You can completely ignore the UI elements and just focus on the logical code.
No need to test fullcalendar.js since Javascript doesn’t need to be tested!
David
Thanks David. I’ll read through that template!