function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
furamagfuramag 

Problem with test class

I am trying to create a testClass for my trigger.
Trigger:

Code:
trigger pd_check on SFDC_PTO_Request__c (before insert, before update) {

SFDC_PTO_Request__c[] opp = trigger.new;

String picklist_v = opp[0].Request_Type__c;

Double count_d_n = opp[0].Days_Off__c;

if (picklist_v == 'Personal days') {

String str = opp[0].Employee__c;
str = str.substring(0,15);

date myDate = opp[0].Request_Start_Date__c;
Integer month = myDate.month();
Integer year = myDate.year();

Double count_d;
Double count_d_b = 0;

Double del;
del = month / 3;
Date from_d;
Date to_d;


if(del <= 1) {
from_d = date.newInstance(year, 1, 1);
to_d = date.newInstance(year, 3, 31);
}
else if((del <= 2) && (del > 1)) {
from_d = date.newInstance(year, 4, 1);
to_d = date.newInstance(year, 6, 31);

}
else if((del <= 3) && (del > 2)) {
from_d = date.newInstance(year, 7, 1);
to_d = date.newInstance(year, 9, 31);
}
else if((del <= 4) && (del > 3)) {
from_d = date.newInstance(year, 10, 1);
to_d = date.newInstance(year, 12, 31);
}



for(SFDC_PTO_Request__c[] s : [SELECT Request_Start_Date__c, Request_End_Date__c, Days_Off__c FROM SFDC_PTO_Request__c WHERE Employee__c = :str AND Request_Type__c = 'Personal days' AND Request_Start_Date__c > :from_d AND Request_Start_Date__c < :to_d]) {


for(SFDC_PTO_Request__c c:s) {
Integer month_s = c.Request_Start_Date__c.month();
Integer month_e = c.Request_End_Date__c.month();
if ((month_s != month_e) && ((month_s / 3 == 1) || (month_s / 3 == 2) || (month_s / 3 == 3) || (month_s / 3 == 4)))
{
count_d_b += 1;
}
else
{
count_d_b += c.Days_Off__c;
}

}

}

count_d = count_d_b + count_d_n;

String count_d_b_t = ''+count_d_b+'';

String[] days = count_d_b_t.split('.');

if(count_d > 2) {

Trigger.new[0].OwnerId.addError('This employee already have 2 or more personal days! Every employee can have only 2 personal day\'s per quarter.');

}

}

else if(picklist_v == 'Vacation'){
//---//
String str = opp[0].Employee__c;
str = str.substring(0,15);

date myDate = opp[0].Request_Start_Date__c;
Integer month = myDate.month();
Integer year = myDate.year();

Double count_d;
Double count_d_b = 0;

Double del;
del = month / 3;
Date from_d;
Date to_d;


if(del <= 1) {
from_d = date.newInstance(year, 1, 1);
to_d = date.newInstance(year, 3, 31);
}
else if((del <= 2) && (del > 1)) {
from_d = date.newInstance(year, 4, 1);
to_d = date.newInstance(year, 6, 31);

}
else if((del <= 3) && (del > 2)) {
from_d = date.newInstance(year, 7, 1);
to_d = date.newInstance(year, 9, 31);
}
else if((del <= 4) && (del > 3)) {
from_d = date.newInstance(year, 10, 1);
to_d = date.newInstance(year, 12, 31);
}



for(SFDC_PTO_Request__c[] s : [SELECT Request_Start_Date__c, Request_End_Date__c, Days_Off__c FROM SFDC_PTO_Request__c WHERE Employee__c = :str AND Request_Type__c = 'Personal days' AND Request_Start_Date__c > :from_d AND Request_Start_Date__c < :to_d]) {


for(SFDC_PTO_Request__c c:s) {
Integer month_s = c.Request_Start_Date__c.month();
Integer month_e = c.Request_End_Date__c.month();
if ((month_s != month_e) && ((month_s / 3 == 1) || (month_s / 3 == 2) || (month_s / 3 == 3) || (month_s / 3 == 4)))
{
count_d_b += 1;
}
else
{
count_d_b += c.Days_Off__c;
}

}

}

count_d = count_d_b + count_d_n;

String count_d_b_t = ''+count_d_b+'';

String[] days = count_d_b_t.split('.');

if(count_d > 2) {

Trigger.new[0].OwnerId.addError('This employee already have 2 or more personal days! Every employee can have only 2 personal day\'s per quarter.');

}
//---//
}


}

 
Test class:
Code:
public class pd_check_test {

    public static testMethod void myUnitTest() {

    SFDC_PTO_Request__c opp = new SFDC_PTO_Request__c(Employee__c = 'a0A70000002lu6N', Request_End_Date__c = Date.newInstance(2009,01,08), Request_Start_Date__c = Date.newInstance(2009,01,01), Request_Type__c = 'Personal days', Details__c = '123456789', Date_of_Request__c = Date.newInstance(2008,12,01));

    insert opp;

    String id = opp.Employee__c;

    SFDC_PTO_Request__c[] s = [SELECT Details__c, Date_of_Request__c FROM SFDC_PTO_Request__c WHERE Employee__c = :id AND Request_Type__c = :opp.Request_Type__c AND Request_Start_Date__c = 2009-01-01 AND Request_End_Date__c = 2009-01-08 AND Details__c = '123456789' LIMIT 1];


Double count_d = 0.0;
Double count_d_b = 0.0;

Double del = 0.0;

   System.assertEquals('123456789', s[0].Details__c); 

    }
}

 My trigger only check how many days off have employee and write error if employee have 2 or more daysoff. It doesn't insert or update something. But when I try to deploy to server I can't do it, because I have only 38% coverage and I have error: "System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, This employee already have 2 or more personal days! Every employee can have only 2 personal day's per quarter.: [OwnerId]". Can somebody help me to write correct test class?

RickyGRickyG
furamag -

Not sure exactly what is wrong with the trigger, but it looks like you are hard coding an ID into the test method (
Employee__c = 'a0A70000002lu6N'

)
Why not create an employee record in the test method and use that?  That way you are sure that there are no accumulated days and you can completely control the test scenario.

Hope this helps.
furamagfuramag
I deleted "Employee__c = 'a0A70000002lu6N'" and have error: "Average test coverage across all Apex Classes and Triggers is 16%, at least 75% test coverage is required".

ShamilShamil
furamag,
please make sure you not simply delete "Employee__c = 'a0A70000002lu6N'" from your SOQL statement, but also:

1. create an Employee__c record first
pseudocode is:

Code:
Employee__c emp = new Employee__c(name='employee_name');
insert emp;

 

2. Use the generated employee Id in your SOQL query:

Code:
SFDC_PTO_Request__c opp = new SFDC_PTO_Request__c(Employee__c = :emp.Id, Request_End_Date__c = Date.newInstance(2009,01,08), Request_Start_Date__c = Date.newInstance(2009,01,01), Request_Type__c = 'Personal days', Details__c = '123456789', Date_of_Request__c = Date.newInstance(2008,12,01));

 Also, your trigger is not a bulk trigger - you are only operating on the first record that is processed by the trigger: Trigger.new[0].
In case of mass updates or data import your logic will only work for the first record.
Check out the cookbook, it has a great example of how to create  a good bulk trigger and a unit test for it:
Cookbook


Good luck!

furamagfuramag
Thank you Shamil.
This is my new test class:
Code:
public class pd_check_test {

    public static testMethod void myUnitTest() {
    
    SFDC_Employee__c emp = new SFDC_Employee__c(Title__c = 'test_employee', SSN__c = '113-12-1984');
 insert emp;
    
    SFDC_Employee__c[] e = [SELECT Title__c, SSN__c FROM SFDC_Employee__c WHERE Id = :emp.Id];
    
    System.assertEquals(emp.Title__c, e[0].Title__c);
    System.assertEquals(emp.SSN__c, e[0].SSN__c);
    
    String emp_id = emp.Id;
    
    SFDC_PTO_Request__c opp = new SFDC_PTO_Request__c(Employee__c = emp.Id, Request_End_Date__c = Date.newInstance(2009,01,02), Request_Start_Date__c = Date.newInstance(2009,01,01), Request_Type__c = 'Personal days', Details__c = '123456789', Date_of_Request__c = Date.newInstance(2008,12,01));

    insert opp;

   System.assertEquals(opp.Details__c, [SELECT Details__c FROM SFDC_PTO_Request__c WHERE Details__c = :opp.Details__c].Details__c);
 
    }
}

 But I still have same problem: "Average test coverage across all Apex Classes and Triggers is 36%, at least 75% test coverage is required".

ShamilShamil

That’s because you are not covering all the scenario’s that your trigger handles.
One example is:
In the trigger you have a variable called del (that depends on Request_Start_Date__c field’s value):

Code:
Double del;
del = month / 3;
 
and then you have a if-else statement that executes different statements depending on del’s value.

Code:
if(del <= 1) {
from_d = date.newInstance(year, 1, 1);
to_d = date.newInstance(year, 3, 31);
}
else if((del <= 2) && (del > 1)) {
from_d = date.newInstance(year, 4, 1);
to_d = date.newInstance(year, 6, 31);

}
else if((del <= 3) && (del > 2)) {
from_d = date.newInstance(year, 7, 1);
to_d = date.newInstance(year, 9, 31);
}
else if((del <= 4) && (del > 3)) {
from_d = date.newInstance(year, 10, 1);
to_d = date.newInstance(year, 12, 31);
}
 When you insert you record in a test method you assign some value to the Request_Start_Date__c field. When the trigger is fired only 1 if-else branch is executed.

Thus, the solution is – insert more records with different field values in your test class. Try to cover all scenarios, execute every branch of your if-else statements
Use System.debug(‘some data’); method to see what exactly is going on in the trigger.

furamagfuramag
Have I to check all variables from my trigger in my test class?
How can I do that? Do you mean something like that:

Code:
date myDate = opp.Request_Start_Date__c;
System.assertEquals (opp.Request_Start_Date__c, myDate);
 My trigger doesn't insert or update data. It only check variables and print error messages. I thought I have to check something only when I insert or update data in database.
ShamilShamil
furamag,

sorry for late answer.
Let's take a closer look at your test method:
You insert a record of a SFDC_PTO_Request__c object: opp.
opp's Request_Start_Date__c is 1st of January, 2009 or  (2009,01,01)
When the record is being inserted the trigger is fired. Now, let's see what happens in this particular piece of code:

Code:
date myDate = opp[0].Request_Start_Date__c;
Integer month = myDate.month();
Integer year = myDate.year();

Double count_d;
Double count_d_b = 0;

Double del;
del = month / 3;
Date from_d;
Date to_d;


if(del <= 1) {
from_d = date.newInstance(year, 1, 1);
to_d = date.newInstance(year, 3, 31);
}
else if((del <= 2) && (del > 1)) {
from_d = date.newInstance(year, 4, 1);
to_d = date.newInstance(year, 6, 31);

}
else if((del <= 3) && (del > 2)) {
from_d = date.newInstance(year, 7, 1);
to_d = date.newInstance(year, 9, 31);
}
else if((del <= 4) && (del > 3)) {
from_d = date.newInstance(year, 10, 1);
to_d = date.newInstance(year, 12, 31);
}

myDate variable is  2009-01-01, hence month variable is equal to 1 and del variable is equal 1/3.
In the if-else statement ONLY the first branch is executed, because 1/3 <= 1

Code:
if(del <= 1) {
from_d = date.newInstance(year, 1, 1);
to_d = date.newInstance(year, 3, 31);
}


 So, out of 4 branches only 1 is executed (25%). To test all the branches of this particular if-else statement you need to insert more SFDC_PTO_Request__c records with different dates.

This is just one example. You have other if-else statements inisde trigger that depend on SFDC_PTO_Request__c records fields. You will need to insert more date to test all conditions.


Fra08Fra08
Hello,
I modified an apex class but I can not upload it in production..
The strange thing is that the system gave me an error about triggers that are already in Salesforce Production... So why the triggers reach only the 41% coverage now? While before they were covering 100%??
Thanks!!