+ Start a Discussion
RKRK 

71% Test Coverage - How to get to 75%

I've made some headway in creating a testmethod for my trigger that will populate a contacts Mobile phone and Phone2 on a newly created task.
However, I can't seem to figure out what to do to get my Test Coverage over 75% (It's currently 71%).

Does anything jump out that might indicate where issue (or most likely, issues) lie?

Trigger Code:
Code:
trigger Copy_Contact_Cell_and_Mobile_To_Task_Record on Task (after insert) 
{
Id ContactIDOnTheTask;
String contactCellNumber;
String contactPhone2;
    for (Task TReadOnly : Trigger.new)
if (TReadOnly.RecordTypeID == '012500000009Kbp')//Limit Code to only FID Tasks
 {//IfOpening
     {
        Task t = [select Id, WhoID from Task where Id = :TReadOnly.Id  limit 1]; //get ContactID
ContactIDOnTheTask= t.WhoID;
Contact[] phoneValueArray = [Select c.Id,c.mobilePhone,c.Phone_2__c from Contact c 
where c.Id = :ContactIDOnTheTask limit 1]; 
for(Integer i=0;i<phoneValueArray.size();i++)
   {//4
contactCellNumber = phoneValueArray[0].mobilePhone;  //grab mobile number from array
contactPhone2 = phoneValueArray[0].Phone_2__c;  //grab phone2 number from array
t.Mobile__c = contactCellNumber;  //set mobile custom field on task to the contact mobile number
t.Phone2__c = contactPhone2;  //set phone2 custom field on task to contact phone2 number
   }//4
  update t;
  }
 }//IfClosing
}

TestMethod:
Code:
public class taskTriggerTestMethod {//1

static testMethod void myTest() {//2
//Declare Variables
Id ContactIDOnTheTask;
String contactCellNumber ;
String contactCellNumber2 ;
String acontactPhoneNumber2;
String bcontactPhoneNumber2;
date taskydate = System.today();
 // Create two Tasks for test
   Task t1 = new task(ActivityDate = taskydate, OwnerId ='00530000000hxwA',   Results__c = 'Contact', Subject='Task1Test', WhoID = '0035000000RzAaw', RecordTypeID = '012500000009Kbp');
insert t1;
 
 Task t2 = new task(ActivityDate = taskydate, OwnerId ='00530000000hxwA', Results__c = 'Contact', Subject='Task2Test', WhoID = '0035000000RzAaw', RecordTypeID = '012500000009Kbp');
 insert t2;  


 //Grab Details From Task 1
 Task t = [select Id, WhoID, Mobile__c,Phone2__c from Task where Id = :t1.Id  limit 1]; //get ContactID


Contact[] phoneValueArray = [Select c.Id,c.mobilePhone,Phone2__c from Contact c 
where c.Id = :t.WhoID limit 1]; 
for(Integer i=0;i<phoneValueArray.size();i++)
   
acontactPhoneNumber2 = phoneValueArray[0].Phone2__c; //grab Phone 2 from array
contactCellNumber = phoneValueArray[0].mobilePhone;  //grab mobile number from array

  
//Grab Details From Task 2
Task t4 = [select Id, WhoID, Mobile__c,Phone2__c from Task where Id = :t2.Id  limit 1]; //get ContactID

Contact[] phoneValueArray2 = [Select c.Id,c.mobilePhone,Phone2__c from Contact c 
where c.Id = :t4.WhoID limit 1]; 
for(Integer i=0;i<phoneValueArray2.size();i++)
   
bcontactPhoneNumber2 = phoneValueArray2[0].Phone2__c;
contactCellNumber2 = phoneValueArray2[0].mobilePhone;  //grab mobile number from array
  
//Tests
  System.assert(t1.ID != NULL);
  System.assert(t2.ID != NULL);
  System.assertEquals(t1.Mobile__c,contactCellNumber);
  System.assertEquals(t2.Mobile__c,contactCellNumber2);
  System.assertEquals(t1.Phone2__c,acontactPhoneNumber2);
  System.assertEquals(t2.Phone2__c,bcontactPhoneNumber2);
 
 } 
}//1

 Debug Log:
Code:
*** Beginning Test 1: taskTriggerTestMethod.static testMethod void myTest()

20080108223753.034:Class.taskTriggerTestMethod.myTest: line 13, column 1: Insert: SOBJECT:Task
*** Beginning Copy_Contact_Cell_and_Mobile_To_Task_Record on Task trigger event bulk AfterInsert for 00T5000000dkDiT

20080108223753.087:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 6, column 5: SelectLoop:LIST:SOBJECT:Task
20080108223753.087:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 10, column 18: SOQL query with 1 row finished in 6 ms
20080108223753.087:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 12, column 29: SOQL query with 1 row finished in 4 ms
20080108223753.087:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 21, column 3: Update: SOBJECT:Task
20080108223753.087:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 21, column 3: DML Operation executed in 28 ms

Cumulative resource usage:

Resource usage for namespace: (default)
Number of SOQL queries: 2 out of 100
Number of query rows: 2 out of 500
Number of DML statements: 2 out of 100
Number of DML rows: 2 out of 500
Number of transaction control statements: 0 out of 0
Number of script statements: 20 out of 200000
Maximum heap size: 0 out of 500000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10

Total email recipients queued to be sent : 0
Static variables and sizes:
Copy_Contact_Cell_and_Mobile_To_Task_Record:ContactIDOnTheTask:18
Copy_Contact_Cell_and_Mobile_To_Task_Record:contactCellNumber:0
Copy_Contact_Cell_and_Mobile_To_Task_Record:contactPhone2:10


*** Ending Copy_Contact_Cell_and_Mobile_To_Task_Record on Task trigger event bulk AfterInsert for 00T5000000dkDiT

20080108223753.034:Class.taskTriggerTestMethod.myTest: line 13, column 1: DML Operation executed in 92 ms
20080108223753.034:Class.taskTriggerTestMethod.myTest: line 16, column 2: Insert: SOBJECT:Task
*** Beginning Copy_Contact_Cell_and_Mobile_To_Task_Record on Task trigger event bulk AfterInsert for 00T5000000dkDiU

20080108223753.155:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 6, column 5: SelectLoop:LIST:SOBJECT:Task
20080108223753.155:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 10, column 18: SOQL query with 1 row finished in 3 ms
20080108223753.155:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 12, column 29: SOQL query with 1 row finished in 5 ms
20080108223753.155:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 21, column 3: Update: SOBJECT:Task
20080108223753.155:Trigger.Copy_Contact_Cell_and_Mobile_To_Task_Record: line 21, column 3: DML Operation executed in 27 ms

Cumulative resource usage:

Resource usage for namespace: (default)
Number of SOQL queries: 4 out of 100
Number of query rows: 4 out of 500
Number of DML statements: 4 out of 100
Number of DML rows: 4 out of 500
Number of transaction control statements: 0 out of 0
Number of script statements: 34 out of 200000
Maximum heap size: 0 out of 500000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10

Total email recipients queued to be sent : 0
Static variables and sizes:
Copy_Contact_Cell_and_Mobile_To_Task_Record:ContactIDOnTheTask:18
Copy_Contact_Cell_and_Mobile_To_Task_Record:contactCellNumber:0
Copy_Contact_Cell_and_Mobile_To_Task_Record:contactPhone2:10


*** Ending Copy_Contact_Cell_and_Mobile_To_Task_Record on Task trigger event bulk AfterInsert for 00T5000000dkDiU

20080108223753.034:Class.taskTriggerTestMethod.myTest: line 16, column 2: DML Operation executed in 63 ms
20080108223753.034:Class.taskTriggerTestMethod.myTest: line 20, column 11: SOQL query with 1 row finished in 3 ms
20080108223753.034:Class.taskTriggerTestMethod.myTest: line 23, column 29: SOQL query with 1 row finished in 6 ms
20080108223753.034:Class.taskTriggerTestMethod.myTest: line 32, column 11: SOQL query with 1 row finished in 3 ms
20080108223753.034:Class.taskTriggerTestMethod.myTest: line 34, column 30: SOQL query with 1 row finished in 6 ms
System.Exception: Assertion Failed: Expected: null, Actual: 1234567890

Class.taskTriggerTestMethod.myTest: line 46, column 3


Cumulative resource usage:

Resource usage for namespace: (default)
Number of SOQL queries: 8 out of 100
Number of query rows: 8 out of 500
Number of DML statements: 4 out of 100
Number of DML rows: 4 out of 500
Number of transaction control statements: 0 out of 0
Number of script statements: 49 out of 200000
Maximum heap size: 0 out of 500000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10

Total email recipients queued to be sent : 0
Stack frame variables and sizes:
Frame0

*** Ending Test taskTriggerTestMethod.static testMethod void myTest()

 


 


Best Answer chosen by Admin (Salesforce Developers) 
TehNrdTehNrd
First off, the trigger you currently have is not written in bulk. This means that any time Tasks may be inserted in mass the trigger will fail. This is because you have 2 SOQL queries in a for loop and you can only execute 20 SOQL calls per trigger execution. That means you would only be able to insert 10 tasks before this trigger fails. Your organization may never insert Tasks in bulk but it is very important you get in the habit of writing triggers in bulk. The same is true for your update statement as it is in a loop as well.

So what we need to do is bulkify/bulkinate/bulkinize this trigger. In this case, it actually makes the trigger a lot simpler.

Code:
trigger help on Task (before insert) {
 
 Set<ID> contactIds = new Set<ID>();
 
 for(Task TReadOnly : Trigger.new){
  contactIds.add(TReadOnly.WhoId);
 }

 Map<Id,Contact> contactMap = new Map<Id, Contact>([Select Id,mobilePhone,Phone_2__c from Contact where Id IN :contactIds]);
  
  for(Task t : Trigger.new){
   if(t.RecordType == '012500000009Kbp'){
   Contact c = contactMap.get(t.WhoId);
    t.Mobile__c = c.mobilePhone;
    t.Phone2__c = c.phone_2__c;
  }
 }
}

As you can see I changed the trigger to execute before Insert and removed the update statement. We do not need to update records that are being modified by the trigger. This is a trigger on tasks and therefore we can set the values on the tasks being processed without having to update them. If with this trigger we wanted to make changes to the related Contacts then we would have to use and 'update' statement to update the contacts. That was sort of confusing but I hope it makes sense.

Make a backup of what you have and then go ahead and try this trigger. If it works (I typed it up in notepad so there may be some syntax issues) like it should report back and we can then look at the test class.


Message Edited by TehNrd on 01-11-2008 02:54 PM

All Answers

RKRK
Well, I've at least isolated what is failing in my code.  For reasons I have not yet figured out, the Trigger is not triggering the update of the Mobile number and the phone 2 number upon the insert contained in the TestMethod.

If I comment out the code below, I get 100% coverage.  Plus, I get a failure message for the first line indicating that it is expecting a NULL, so I know that the t1 and t2 values aren't correct.
 
Code:
  System.assertEquals(t1.Mobile__c,contactCellNumber);
System.assertEquals(t2.Mobile__c,contactCellNumber2);
System.assertEquals(t1.Phone2__c,acontactPhoneNumber2);
System.assertEquals(t2.Phone2__c,bcontactPhoneNumber2);

Also, if I hard code the contact phone number 2 into the test, this passes as well.  So - I now know that the t1 values are in fact not populating (which should happen via the trigger).
Code:
System.assertEquals('(847) 402-1234',bcontactPhoneNumber2);

 


I am now doing this in my dev org, so I can safely see that the trigger actually works in real time.
And, I believe that I am querying properly and I beleive that my test tasks (t1 and t2) are creating properly, because if I do the test below, it checks out OK.


Code:
System.assertEquals(t1.Results__c, 'Contact');

 






Message Edited by RK on 01-08-2008 08:28 PM
mahimahi
RK-
 
Try this:
 
Create one contact in your dev org and put that contact's Id into WhoId (If you want to hardcode WhoId field)
 
  OR
 
Contact con= new Contact(name='abc');
insert con;
 
 Task t2 = new task(ActivityDate = taskydate, OwnerId ='00530000000hxwA', Results__c = 'Contact', Subject='Task2Test', WhoID = con.id, RecordTypeID = '012500000009Kbp');
 insert t2;
 
I think it should work.
 
Regards,
Mahi
RKRK
Mahi,
Thank you for the guidance & suggestion!
I did the first proposal you suggested...hard coded an actual ID of an already-created contact that exists within my dev org.  Code is as follows:


Code:
Task t1 = new task(ActivityDate = taskydate, OwnerId ='00530000000hxwA',
Results__c = 'Contact', Subject='Task1Test', WhoID = '0035000000RzAaw', 
RecordTypeID = '012500000009Kbp');

insert t1;

 The reason I don't think the trigger is populating the fields on the contact is becuase the test below, which attempts to verify that the Mobile custom field on the Task record equals the mobile number on the contact record, fails
Code:
System.assertEquals(t1.Mobile__c,contactCellNumber);

//This test is failing with the message below.
//System.Exception: Assertion Failed: Expected: null, Actual: 1234567890
//The contactCellNumber is evaluating to 1234567890, which is what it is
//on the contact, but the t1.Mobile__c is evalutating to Null. This
//field should be triggered to be the same as that on the contact record.

 Likewise, if I hard code in the known phone number for the contact, the query of the mobile phone number for the contact tests out OK.  Also, if I remove all instances of the t1.Variable and substitute the actual numbers, everything passes properly.  This indicates to me that the query of the contact works properly
Code:
System.assertEquals('1234567890',contactCellNumber);

//This evaluates to True.

 







Message Edited by RK on 01-09-2008 08:01 AM
RKRK
So close...

I've been trying to do some parallel testing in my Dev org (which is where I originally developed the trigger).  And from what I can tell from the output of the "Run Test", everthing is evalauting to True:
Code:
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 29, column 1: SelectLoop:LIST:SOBJECT:Task
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 29, column 20: SOQL query with 3 rows finished in 3 ms
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 33, column 1: The mobile number on task0 is [12345]
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 34, column 1: The mobile number on the contact is [12345]
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 33, column 1: The mobile number on task1 is [12345]
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 34, column 1: The mobile number on the contact is [12345]
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 33, column 1: The mobile number on task2 is [12345]
20080110143441.246:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 34, column 1: The mobile number on the contact is [12345]
20080110143441.246:Class.UpdateContactOnAccountChangeTester: line 3, column 24: returning from end of method static testMethod void accountUpdateSyncToContacts() in 255 ms

 

So I beleive I've proven that (in dev, at least), my code is sound.

When I attempt to validate them in Production, I get the following message for the same area of the code:
Code:
Evaluation20080110150424.272:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 18, column 1:     DML Operation executed in 496 ms
20080110150424.272:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 23, column 1: SelectLoop:LIST:SOBJECT:Task
20080110150424.272:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 23, column 19: SOQL query with 3 rows finished in 6 ms
20080110150424.272:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 27, column 1: The mobile number on task0 is [null]
20080110150424.272:Class.UpdateContactOnAccountChangeTester.accountUpdateSyncToContacts: line 28, column 1: The mobile number on the contact is [12345]
System.Exception: Assertion Failed: Expected: 12345, Actual: null

So, the task mobile and phone2 isn't getting affected by the trigger that I'm trying to deploy in conjunction with the Test Class.

Am I missing something?  Do I need to do them in a different order?  I feel like it is something small that I'm not getting here, but that may not be the case...


TehNrdTehNrd
First off, the trigger you currently have is not written in bulk. This means that any time Tasks may be inserted in mass the trigger will fail. This is because you have 2 SOQL queries in a for loop and you can only execute 20 SOQL calls per trigger execution. That means you would only be able to insert 10 tasks before this trigger fails. Your organization may never insert Tasks in bulk but it is very important you get in the habit of writing triggers in bulk. The same is true for your update statement as it is in a loop as well.

So what we need to do is bulkify/bulkinate/bulkinize this trigger. In this case, it actually makes the trigger a lot simpler.

Code:
trigger help on Task (before insert) {
 
 Set<ID> contactIds = new Set<ID>();
 
 for(Task TReadOnly : Trigger.new){
  contactIds.add(TReadOnly.WhoId);
 }

 Map<Id,Contact> contactMap = new Map<Id, Contact>([Select Id,mobilePhone,Phone_2__c from Contact where Id IN :contactIds]);
  
  for(Task t : Trigger.new){
   if(t.RecordType == '012500000009Kbp'){
   Contact c = contactMap.get(t.WhoId);
    t.Mobile__c = c.mobilePhone;
    t.Phone2__c = c.phone_2__c;
  }
 }
}

As you can see I changed the trigger to execute before Insert and removed the update statement. We do not need to update records that are being modified by the trigger. This is a trigger on tasks and therefore we can set the values on the tasks being processed without having to update them. If with this trigger we wanted to make changes to the related Contacts then we would have to use and 'update' statement to update the contacts. That was sort of confusing but I hope it makes sense.

Make a backup of what you have and then go ahead and try this trigger. If it works (I typed it up in notepad so there may be some syntax issues) like it should report back and we can then look at the test class.


Message Edited by TehNrd on 01-11-2008 02:54 PM
This was selected as the best answer
Jerry HongJerry Hong

covered codes and uncovered codes are labeled in different colors