0

I have written a test class for the Schedualble class and the if condition is not getting covered.The code coverage is displaying as 40% .Any Suggestion please.

Schedule Class :

global class ResponseDaysCalulatorScheduler implements Schedulable
{
    global void execute(SchedulableContext ctx)
    {      
        CalculateDaysToResponse.UpdateResponseDaysForCampaignMember();
    }   
}

Test Class :

    @Istest
public class CalculateDaysToResponseTest{
public static testmethod void  UpdateResponseDaysForCampaignMemberTest(){

 Test.startTest();

Date todayDate = system.today();

Lead lea = new lead(lastname='Test',company='test', email='abc@test.com',Approval_flag__c=false,
                    Approval_Status__c='Pending Approval',Country='USA',Status='Not Contacted'); 
        insert lea;
       system.debug('=======================:'+(lea.lastname));


 Contact cont = new Contact(FirstName ='Testing' ,LastName='Response Days Calculation');
 insert cont;
 system.debug('=======================:'+(cont.FirstName));

 Campaign camp = new Campaign(Name='testing days',CurrencyIsoCode='USD',Score__c='100',Type='Inquiry',Status='Not Contacted');
 insert camp;
 system.debug('=======================:'+(camp.Name));

 list<CampaignMember> newcampaignmem = new list<CampaignMember>();
 CampaignMember campmem = new CampaignMember(Days_to_Response__c=7,CurrencyIsoCode='USD',ContactID=cont.id,CampaignID=camp.Id,
                                             Response_Date__c=Date.Today(),Disqualified_Reason__c='other',LeadId=lea.Id );
                                             newcampaignmem.add(campmem);
                                             system.debug('=======================:'+(campmem.CurrencyIsoCode));
                                             system.debug('=======================:'+(campmem.Response_Date__c));

  insert newcampaignmem;
  campmem.Days_to_Response__c=7;
  update newcampaignmem;

 // Test.startTest();
 ResponseDaysCalulatorScheduler sh1 = new ResponseDaysCalulatorScheduler();
 String sch = '0 0 23 * * ?'; 
 system.schedule('ResponseDaysCalulatorScheduler Check', sch, sh1); 
  //list<CampaignMember> newcampaignmem = new list<CampaignMember>();
 Test.stopTest();

  }
 public static testmethod void  UpdateResponseDaysForCampaignMemberTest1(){

 Test.startTest();

Date todayDate = system.today();

Lead lea = new lead(lastname='Test1',company='test', email='abc@test.com',Approval_flag__c=false,
                    Approval_Status__c='Pending Approval',Country='USA',Status='Not Contacted'); 
        insert lea;
          system.debug('&&&&&&&&&&&&&&&&&&:'+(lea.lastname));

 Contact cont = new Contact(FirstName ='Testing1' ,LastName='Response Days Calculation');
 insert cont;
  system.debug('&&&&&&&&&&&&&&&&&&&:'+(cont.FirstName));
 Campaign camp = new Campaign(Name='testing days1',CurrencyIsoCode='USD',Score__c='100',Type='Inquiry',Status='Not Contacted');
 insert camp;
 system.debug('&&&&&&&&&&&&&&&&:'+(camp.Name));

 list<CampaignMember> newcampaignmem = new list<CampaignMember>();
 CampaignMember campmem = new CampaignMember(Days_to_Response__c=7,CurrencyIsoCode='USD',ContactID=cont.id,CampaignID=camp.Id,
                                             Response_Date__c=Date.Today().addDays(-1),Disqualified_Reason__c='other',LeadId=lea.Id );
                                             newcampaignmem.add(campmem);
                                               system.debug('&&&&&&&&&&&&&&&&&&&&&:'+(campmem.CurrencyIsoCode));
                                               system.debug('&&&&&&&&&&&&&&&&&&&:'+(campmem.Response_Date__c));

  insert newcampaignmem;
  campmem.Days_to_Response__c=7;
  update newcampaignmem;

 // Test.startTest();
 ResponseDaysCalulatorScheduler sh1 = new ResponseDaysCalulatorScheduler();
 String sch = '0 0 23 * * ?'; 
 system.schedule('ResponseDaysCalulatorScheduler Check', sch, sh1); 
  //list<CampaignMember> newcampaignmem = new list<CampaignMember>();
 Test.stopTest();

  }
  public static testmethod void  UpdateResponseDaysForCampaignMemberTest2(){

 Test.startTest();

Date todayDate = system.today();

Lead lea = new lead(lastname='Test2',company='test', email='abc@test.com',Approval_flag__c=false,
                    Approval_Status__c='Pending Approval',Country='USA',Status='Not Contacted'); 
        insert lea;
          system.debug('*********************:'+(lea.lastname));

 Contact cont = new Contact(FirstName ='Testing2' ,LastName='Response Days Calculation');
 insert cont;
  system.debug('*****************:'+(cont.FirstName));

 Campaign camp = new Campaign(Name='testing2 days',CurrencyIsoCode='USD',Score__c='100',Type='Inquiry',Status='Not Contacted');
 insert camp;
 system.debug('**********************:'+(camp.Name));

 list<CampaignMember> newcampaignmem = new list<CampaignMember>();
 CampaignMember campmem = new CampaignMember(Days_to_Response__c=10,CurrencyIsoCode='USD',ContactID=cont.id,CampaignID=camp.Id,
                                             Response_Date__c=Date.Today().addDays(1),Disqualified_Reason__c='other',LeadId=lea.Id );
                                             newcampaignmem.add(campmem);
   system.debug('**************:'+(campmem.CurrencyIsoCode));
   system.debug('**************:'+(campmem.Response_Date__c));
  insert newcampaignmem;
  campmem.Days_to_Response__c=0;
  update newcampaignmem;

 // Test.startTest();
 ResponseDaysCalulatorScheduler sh1 = new ResponseDaysCalulatorScheduler();
 String sch = '0 0 23 * * ?'; 
 system.schedule('ResponseDaysCalulatorScheduler Check', sch, sh1); 
  //list<CampaignMember> newcampaignmem = new list<CampaignMember>();
 Test.stopTest();

  }
  }

Class :

    public class CalculateDaysToResponse{
    public static void UpdateResponseDaysForCampaignMember(){
    List<CampaignMember> NewmatchingMembers = new List<CampaignMember> ();
    List<CampaignMember> matchingMembers = new List<CampaignMember> ();

    if(Test.isRunningTest()) matchingMembers = [SELECT Id, Response_Date__c, Days_to_Response__c, Campaign_Type__c, Lead_Status__c  FROM CampaignMember WHERE Response_Date__c != null AND Campaign_Type__c = 'Inquiry'];
    else matchingMembers = [SELECT Id, Response_Date__c, Days_to_Response__c, Campaign_Type__c, Lead_Status__c FROM CampaignMember WHERE Response_Date__c != null AND Campaign_Type__c = 'Inquiry' AND Lead_Status__c = 'Not Contacted'];

    for(CampaignMember matchingMember : matchingMembers)
    {
        Date todayDate = system.today();
        if(matchingMember.Response_Date__c < todayDate)
        {
            Integer diff = matchingMember.Response_Date__c.daysBetween(date.valueof(Date.today()));
            matchingMember.Days_to_Response__c = diff;             
        } else {
            matchingMember.Days_to_Response__c = 0;
        }            
       NewmatchingMembers.add(matchingMember);
    }  
    update NewmatchingMembers ;
    }
}

Any Suggestion very much appreciated.

  • You need to write several test methods - they can share code via other methods you define and call - that setup data so that each if/else branch is taken. That is as well as a test with Date.Today().addDays(-1) you need a test with Date.Today().addDays(1). – Keith C Mar 09 '16 at 12:28
  • As mentioned by @KeithC, you need to have multiple test methods. You need to have your campaign records Response_Date__c to have todays date in one test method. In the next test method it should have Date.Today().addDays(-1) and the last one should have Date.Today().addDays(1) – Prady Mar 09 '16 at 12:47
  • In addition to what has been said above, I think there are 2 distinct things to test: that your scheduler class is calling CalculateDaysToResponse.UpdateResponseDaysForCampaignMember();, and then the behaviour of the method itself. I would turn that into 2 different test classes, but if you're testing the behaviour of your CalculateDaysToResponse class, there's no need to schedule it. – mkorman Mar 09 '16 at 13:03
  • @KeithC,@Prady:Thanks for your response.As suggested i have tested with multiple test methods but still the code coverage is 40%.I have update the test code.Any Suggestions very much appreciated. – SalesforceCRM AccountCRM Mar 09 '16 at 13:07
  • @mkorman:Thanks for your reply.I looking forward for the behaviour of CalculateDaysToResponse class as weel for the schedule.To main Criteria is to increase the code coverage.Any help very much appreciated. – SalesforceCRM AccountCRM Mar 09 '16 at 13:11
  • @SalesforceCRMAccountCRM. It would help immensely if you told us what lines in your code aren't being covered by your test class. Please edit your code and wrap your lines with //*** Start Not Covered ***// and //*** End Not Covered ***// so we can give you more specific direction on how to solve your issues. – crmprogdev Mar 09 '16 at 15:00
  • @SalesforceCRMAccountCRM. Just a thought, I noticed from looking at the data you create, unless you have default values for campaign, workflow or triggers that fire, you're not populating all of the fields you're querying. This could cause your code coverage to be low. Have you looked at your debug logs? – crmprogdev Mar 09 '16 at 15:08
  • @crmprogdev:Thanks for your response.I have added the lines which are not covered in developer console in a separate block.I have added all the mandatory fields while doing an insertion of campaign and campaign member.In the query of Campaign member the Campaign_Type__c and Lead_Status__c both are formula field which is taken from (Type )Campaign and( Status) from Lead.Any Help very much appreciated. – SalesforceCRM AccountCRM Mar 09 '16 at 16:53
  • For diff to be = 0, Response_Date__c in your test data must = today(), correct? You must cover both the If and the else conditions to increase your code coverage. With the correct data, that should be happening. If you used more than one lead with diff values in the same method, it would. You don't know if it is, because you have no debug statements. See How do I start to debug my own Apex code?. – crmprogdev Mar 09 '16 at 17:06
  • N. B. There are no asserts in the testmethods so even if you achieved 100% code coverage you would t know if your code was correct. – cropredy Mar 09 '16 at 18:20
  • @crmprogdev,@crop1645:I have added the debug stmts in logs it displays the value but the code coverage is still 40% only.Any suggestion please. – SalesforceCRM AccountCRM Mar 10 '16 at 14:54
  • @crmprogdev,@crop1645,@Prady :When i add if(Test.isRunningTest()) and query in the class ,the code coverage got increased to 92%.But unable to deploy the code bcoz i get the code coverage error while deploying .The code coverage is 73% in production.To improve the code coverage im writing the test classes.But no luck stil.Any Suggestion very much appreciated. – SalesforceCRM AccountCRM Mar 10 '16 at 18:23
  • @SalesforceCRMAccountCRM. I suggest you update your post with your revised code. Also, it sounds to me as though when your coverage was stuck at 40%, you were only running the single method and not all methods in your test class. When you say coverage in production is only 73%, do you mean for all classes? If so, you need to increase code coverage on other classes before you can deploy. That frequently happens when SF features have been enabled that use classes which need customized for an org. Communities is one of many that come to mind (the login controller). – crmprogdev Mar 10 '16 at 20:51
  • @crmprogdev:I have updated the code .In apex class we have added two lines (if(Test.isRunningTest()) matchingMembers )In Sandbox the test class is code coverage is displaying as 92% .In production the overall code coverage is displaying as 73%.Its been a from two weeks i have been writing the test classes for other classes and triggers where the code from 23% came to 73% .I had a test class yesterday which had a code coverage as 50% and making modification the code got increased to 85% .deployed the code in production and ran all the test classes the overall code coverage displayed as 73% . – SalesforceCRM AccountCRM Mar 11 '16 at 12:30

1 Answers1

1

You've not fully implemented the recommendations regarding system.debug statements and system.asserts. Here's a few suggestions on your test class:

insert newcampaignmem;
// you may want to add a query to validate that your record were inserted properly and assert the results

campmem.Days_to_Response__c=7;

update newcampaignmem;
// Add query to get results confirming update and assert expected results

In the class you're writing the test class for:

    public class CalculateDaysToResponse{
    public static void UpdateResponseDaysForCampaignMember(){
    List<CampaignMember> NewmatchingMembers = new List<CampaignMember> ();
    List<CampaignMember> matchingMembers = new List<CampaignMember> ();

    if(Test.isRunningTest()) matchingMembers = [SELECT Id, Response_Date__c, Days_to_Response__c, Campaign_Type__c, Lead_Status__c  FROM CampaignMember WHERE Response_Date__c != null AND Campaign_Type__c = 'Inquiry'];
    //***add system debug statement here to verify results are returned in matching Members
    //***if Test.isRunningTest() isn't necessary

    else matchingMembers = [SELECT Id, Response_Date__c, Days_to_Response__c, Campaign_Type__c, Lead_Status__c FROM CampaignMember WHERE Response_Date__c != null AND Campaign_Type__c = 'Inquiry' AND Lead_Status__c = 'Not Contacted'];

    for(CampaignMember matchingMember : matchingMembers)
    {
        Date todayDate = system.today();
        //***add system debug statement to display matchingMember.Response_Date__c
        if(matchingMember.Response_Date__c < todayDate)
        {
            Integer diff = matchingMember.Response_Date__c.daysBetween(date.valueof(Date.today()));
            matchingMember.Days_to_Response__c = diff;
            //***add system debug statement to display both matchingMember.Response_Date__c and diff            
        } else {
            matchingMember.Days_to_Response__c = 0;
            //***add system debug statement to display both matchingMember.Response_Date__c and diff
        }             
       NewmatchingMembers.add(matchingMember);
       //***add system.debug to get NewmatchingMembers.size()
    }  
    update NewmatchingMembers ;
    }
}

When you're testing a schedulable class it's Test.stopTest() that causes it to execute. That's why you don't need the if(Test.isRunningTest()) at the beginning of your query (it's not running at that point in your test class). The class only runs AFTER Test.stopTest(). You'll also want to validate your results at the end of Test.stopTest() which is also why you need to have the debug statemens in your schedulable class, so you can see what's happening there.

Further tips you'll want to learn:

integer n=1; // use this to set number of records you want to test at a time
list<lead>ld = new list<lead>();
list<contact>ctc = new list<contact>();
Campaign camp = new Campaign(Name='testing2 days',CurrencyIsoCode='USD',Score__c='100',Type='Inquiry',Status='Not Contacted');
insert camp;
system.debug('**********************:'+(camp.Name));
//*** get camp.Id to assure the campaign was inserted! You already know camp.Name.
list<CampaignMember> newcampaignmem = new list<CampaignMember>();

for(integer i=0;i<n;i++)
{
ld[i] = new lead(lastname='Test+i',company='test+i', email='abc+i@test.com',Approval_flag__c=false,
                    Approval_Status__c='Pending Approval',Country='USA',Status='Not Contacted'); 

ctc[i] = new Contact(FirstName ='Testing+i' ,LastName='Response Days Calculation + i');
//*** Note: Normally a contact requires an email address, would be surprised if these are inserting w/o errors

newcampaignmem[i] = new CampaignMember(Days_to_Response__c=10,CurrencyIsoCode='USD',ContactID=cont[i].id,CampaignID=camp.Id,
                                         Response_Date__c=Date.Today().addDays(1),Disqualified_Reason__c='other',LeadId=ld[i].Id );


}

insert ld;

insert ctc;

insert newcampaignmem;

You now would have lists of leads, ctcs and campaigns to use for bulk testing or single record testing depending on the value you set for n just by changing the value of that integer using the same method(s) (max of 200).

You could even use different values for campmem.Days_to_Response__c if you set n = 3 so you'd only need one test method if you used multiples of i*n to determine which value to use (sometimes easier to add one to i for the calculation & you'll also need if statments). Your asserts will still be predictable by tracking the value of either i or the record Id.

crmprogdev
  • 40,955
  • 9
  • 58
  • 115