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
deryckjderyckj 

Code coverage, trying to learn and out of time

Please point me in the right direction.  I've spent the past two days trying to sort through examples that might apply and am just confusing myself more and more....I've run out of time and must get this code deployed to production.  Here's a sample - any help greatly appreciated:

 

This is one of six classes and six triggers that I have to get coverage on...not sure of the best way to proceed.  Thanks in advance!

 

publicwithsharingclass Lead_Creation {

 

    public String searchTerm {get; set;}

    public List<Lead> returnedLeads {get; set;}

    public Boolean isNewLead {get; set;}

    public String SelectedCampaignId {get; set;}

    public String SelectedCampaignName {get; set;}

      

    private Account SelectedProject;

    public Lead currentLead {get; set;}

    

    

    public String SelectedExtension {get; set;}

    public List<SelectOption> getExtensionsOptions()

    {

        SelectedCampaignId = '';

        SelectedCampaignName = '';

        currentLead.Ad_Type__c  = null;

        List<SelectOption> options = new List<SelectOption>();

        options.add(new SelectOption('None','--None--'));

        SelectedExtension = options[0].getLabel();

        for(Campaign c : [SELECT Project_Code__c, Extension__c, Media_Source__r.Name

                          Ad_Size__c, Ad_Type__c FROM Campaign WHERE Project__c =: currentLead.Project_Site__c AND RecordType.Name != 'Parent'])

        {

            string AdType = (c.Ad_Type__c != null ? c.Ad_Type__c : '');

            string AdSize = (c.Ad_Size__c != null ? c.Ad_Size__c : '');

            String ext = c.Project_Code__c+'-'+string.valueof(c.Extension__c)+'-'+c.Media_Source__r.Name+'-'+AdType+'-'+AdSize ;

            options.add(new SelectOption(ext,ext));

        }

        

        if(options.size() == 2)

        {

            SelectedExtension = options[1].getLabel(); 

            populateAdvertizingInfo();

        }

        

        return options;

    }

 

    {

        isNewLead = false;

        

    }

    public Lead_Creation(ApexPages.StandardController controller) {

        currentLead = (Lead)controller.getRecord();

        currentLead.Status = 'Unassigned';

        currentLead.LastName = ' ';

        currentLead.ownerid = UserInfo.getUserId();

    }

    

    public void fetchLeads()

    {

        returnedLeads  = new List<Lead>();

        

        String searchCriteria = '%'+searchTerm+'%';

        

        returnedLeads  = [Select Id, Name, Email, Phone, City, Street, State, Country, Status, Owner.Name, Ownerid

                            FROM Lead 

                            WHERE Email Like : searchCriteria OR Phone Like : searchCriteria  OR Name Like : searchCriteria  Limit 1000];

                            

        if(returnedLeads.isEmpty())

        {

            ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.Confirm,'This is a New Lead'));

        }else

        {

            ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.Warning,'Similar Leads were found, please verify the list below'));

        }

    }

    

    private Campaign thisCampaign ;

    public void populateAdvertizingInfo()

    {

        List<String> SelectedAdSeries = SelectedExtension.split('-');

        Decimal ext = Decimal.valueof(SelectedAdSeries[1]);

        thisCampaign = [Select Campaign_Fully_Qualified__c, Ad_Type__c, Ad_Size__c, Media_Source__c, Project_Code__c,

                       Type from Campaign where Project__c =: currentLead.Project_site__c AND Extension__c =: ext LIMIT 1];

        system.debug('the campaign '+thisCampaign.id);

        currentLead.Ad_Type__c = thisCampaign.Ad_Type__c;

        currentLead.Ad_Size__c = thisCampaign.Ad_Size__c;

        currentLead.Media_Source__c = thisCampaign.Media_Source__c;

        currentLead.Project_Code__c = thisCampaign.Project_Code__c;

        currentLead.Ad_Series__c = thisCampaign.Campaign_Fully_Qualified__c;

        SelectedCampaignID = thisCampaign.Id;  

        SelectedCampaignName = thisCampaign.Campaign_Fully_Qualified__c;

    }

    

    public void getExtensions()

    {

        getExtensionsOptions();

    }

    

    public PageReference createNewLead()

    {

        isNewLead = true;

 

        return null;

    }

    

    public PageReference saveExt()

    {

        integer err = 0;

        if(currentLead.LastName != null && currentLead.Status != null)

        {

            try{

                currentLead.Extension__c = SelectedExtension;

                insert currentLead;

                

            }catch(Exception e)

            {

                system.debug('the error'+e.getMessage());

                err++;

                return null;

            }

        }else

        {

            if(currentLead.LastName == null)

                currentLead.LastName.addError('This field is required');

            if(currentLead.Status == null)

                currentLead.Status.addError('This field is required');

            return null;

        }

            

        if(err == 0)

        {

            CampaignMember newCM = newCampaignMember(

                                            CampaignId = thisCampaign.id,

                                            LeadId = currentLead.Id,

                                            Status = 'Responded'

                                        );

                

            try{

                insert newCM;

            }catch(Exception e)

            {

                system.debug('the error'+e.getMessage());

            }

            

        }

        

        return new PageReference('/'+currentLead.Id);

    }

 

}

sfdcfoxsfdcfox

Testing is easy. The point of test methods is to make sure that your logic is flowing correctly. Testing will always flow in a certain pattern: setup, execution, validation, and tear-down.

 

For example, given a trigger on an opportunity, your test method would look like this:

 

static testMethod void test() {
    // Setup
    Account a = new Account(Name='test', CreditRating__c='A-');
    insert a;
    Opportunity o = new Opportunity(Name='Test', AccountId=a.id, StageName='Prospecting', CloseDate=System.Today(), Probability=0.10);
    // Execution
    Test.startTest();
    insert o;
    Test.stopTest();
    // Validation
    o = [SELECT Id, CreditPlan__c FROM Opportunity WHERE Id = :o.Id];
    System.assertEquals('90 Day Trial', o.CreditPlan__c);
    // Tear-down
}

Note that I included tear-down even though there's nothing to do. This is only intended as illustrative, because tear-down in salesforce.com is automatic. In other languages, tear-down includes deallocating memory, closing sockets, deleting temp tiles, and doing other things to clean up after the test. You'll need to know about tear-down if you later branch into other languages.

 

Salesforce.com automatically rolls back the entire transaction, leaving (virtually) no trace of having run the test. As a matter of performance, your auto-number fields won't be reset, so they will be incremented by the number of records involved in the test. This usually isn't a big deal, but you should note this, because things like contracts and cases will have missing sequence numbers when you run tests. Everything else will be left intact; deleting production data, for example, won't actually move the records to the recycle bin.

 

In terms of salesforce.com specific execution, you should be aware of the following best practices:

 

Do Not Depend on Production Data


To the largest extent possible, you should never hard-code an ID value or query for existing data. Instead, create all the data you'll need in the setup phase. Salesforce.com provides two governor limits to facilitate this design pattern: your test method has a separate set of limits to create data, and using Test.startTest() resets the governor limits to zero so you can perform the logic without the prior used limits. Test.stopTest() will return back to the first set of governor limits, execute asynchronous code, etc. However, you may need to make some assumptions, like record types, etc. In this case, query the data instead of hard-coding the ID values.

 

Test Borderline and Unusual Conditions

 

Test borderline conditions, such as what happens when the user enters in barely legal and barely illegal values. For example, if your code expects a percentage from 0 to 100, test -1%, 0%, 100%, and 101%. Use multiple tests if you would like. Also test for what happens when users don't enter a value in a given field (either the system should give an error, or the code should complete successfully; an uncaught thrown exception is a test failure).

 

Test Bulk Processing when Practical


This is especially important for triggers and batch processing classes. Make a list of 200 items, and try to insert/update/delete/etc those records as a single transaction. You can create the items in a loop so that you don't need 200 lines of code to create 200 items manually. Also try to test partial pass/fail conditions, such as leaving a required field blank for just a single record. Properly written triggers should be able to handle this condition gracefully. You can use the Database methods that take the optional Boolean parameter specifying that a partial success is allowed.

 

Aim for Code Coverage


This is a primary objective, but in order to make the testing practical, limit the number of test methods that need to be written to just a handful. This will avoid running into limits in regards to testing. It's often possible to test an entire trigger, including all possible branches, in just a few DML statements. It's also often worth moving the database logic to a utility class that you can test independently of the trigger itself. This gives more flexibility in how the test coverage is achieved, and makes validating subroutines with a trigger easier (thanks to @TestVisible, etc).

 

Start From the Top and move Down

 

This doesn't mean trying to cover each line of code in numerical order, but rather in order of execution. This tip is primarily for classes. Your test should start with all the possible constructors for the class(es) being tested, then all non-DML methods should be tested (such as navigating through pages, searching for records, etc), and finally all DML methods should be tested. Give priority to normal execution flows, but do try to cover exceptions as much as possible. The more assert methods you use, the more likely you'll find bugs before your users do.

 

Since time is of importance, you should focus on coverage before veracity, but you should always advise interested parties that the testing should be completed. In all but the simpliest applications, testing every possible scenario is largely impossible, but you should strive to cover as many as you can in the time you have available.

deryckjderyckj
This is a tremendous answer - thank you! After two days of wandering aimlessly, I feel a bit more focused. I will get back to you with specific questions as I work my way through your response.

Warm regards
deryckjderyckj

So, to break this down into a small first step...I wrote this:

 

@isTest

private class Lead_creation_TestClass {

 

    static testMethod void Lead_creation_testclass() {

  

 //setup

 

 Lead a = new Lead(name='Treat', project_code__c='EN1');

 

 //execution

 Test.startTest();

 insert a;

 test.stopTest();

 

 //Validation

 a = [SELECT name, project_code__c FROM Lead WHERE name = 'Treat'];

    System.assertEquals('EN1', a.project_code__c); 

  

    }

}

 

//however, I get this error in the IDE 

Description Resource Path Location Type
Save error: Field is not writeable: Lead.Name Lead_creation_TestClass.cls   This has happened to me constantly.  Not sure what I am doing wrong.  The field is a valid field in the Lead object.

deryckjderyckj
Figured this one out. Now just need to expand to get full coverage.
sfdcfoxsfdcfox
Glad I could get you started. Feel free to ask if you have any more questions.
deryckjderyckj
I have a deadline to get these done by Monday morning. I don't think I am going to make it. Do you know anyone that would do this over the weekend for me for pay? (Am I allowed to ask this on the forum? - if not, forgive my ignorance).
deryckjderyckj

 Lead a = newLead(project_site__c='Test Account5', status='unassigned', Ad_series__c= 'TA5-X2-Boston HeraldNewspaper-Display-Full Page', LeadSource='Advertisement', Rating='Warm', lastname='Treat', project_code__c='TA5', ad_size__c='1/8 page', Media_Source__c='Boston Herald');

 

 

This line is failing, I believe, because it has a couple of lookups.  How do I write the code around those.  For example, project_site__c='Test Account5' is actually a lookup field.  Test Account5 is a correct value but does this have to be written a different way?  It fails on TestRunner with a string exception error.

deryckjderyckj

One other question,

 

When I write these test classes, can they all be in one class file?  And, if so, do they each get seperated with the statement like this:

 static testMethod void Lead_creation_testclass() { where i would subsititute Lead_creation_testclass() with ProjectAccount_created.trigger if for one of my triggers?

k_bentsenk_bentsen

Look-ups fields can be assigned by reference of the id of the object that is looked up. For example:

 

project_site__c = TestAccount5.Id

 

This of course assumes that TestAccount5 is the variable name of the test account record, and the Id field is accessible by the system.

 

Also, I would recommend that you spend some time over the weekend figuring this out. The experience and understanding you'll learn while working this out will likely be much more valuable than having someone else do it for you.

deryckjderyckj

Thanks...oh, and I will be working on this all weekend, regardless.  I'm more concerned about meeting our deadline.

 

Your response on the id helped, thank you.  Now, can all of the test cases be put into a single class or should each test case be put into it's own class?

sfdcfoxsfdcfox
I always accept freelance work. Pm me if you need help.