1

I created a scheduled job to run all tests in org at 5:30 AM, and another one at 6:00 AM(to ensure that all test jobs done) to send the code coverage percentage and top 10 uncovered classes in org,the email contains class name,Total lines & uncovered lines.

The same class that sends the email is a controller for VF page that

My problem is that the data sent by email is wrong data,not the actual coverage,since I created the scheduled job I got the same email,for example

There's a class named test_ftn,this class was 289 Lines,and now it's 0 lines but I still see it in the sent report.

I tried to call the constructor in the execute code block,to ensure that a fresh data is fetched,but I got an error that the session id is null,I need to use http request because the coverage object is tooling api and can't be queried from apex.

This is my scheduled class (page controller) :

global class CodeCoverageController implements schedulable{


    public Id jobid{get
        {
            code_coverage__c cc=[select job_name__c,last_job_id__c,date__c from code_coverage__c where job_name__c='last'];
            return cc.last_job_id__c;
        }
        set;}

    public integer alltests{  
        get{
            if(jobid==null) return 0; 
            //if(alltests!=0) return alltests;
            string query='select count() from ApexTestQueueItem where ParentJobId=\''+JobId+'\'';
            return database.countQuery(query);
        }
    }

    public integer done{
        get{
            if(jobid==null) return 0;
            string query='select count() from ApexTestQueueItem  where ParentJobId=\''+JobId+'\' AND (status=\'completed\' OR status=\'Failed\')';
            return database.countQuery(query);
        }
    }

    public integer notdone{ 
        get{
            if(jobid==null) return 0;
            string query='select count() from ApexTestQueueItem  where ParentJobId=\''+JobId+'\' AND (status=\'Queued\' OR status=\'Processing\')';
            return database.countQuery(query);
        }
    }

    public string imgurl{get;set;}
    public string cssclass{get;set;}
    public integer allcovered{get;set;}
    public integer alluncovered{get;set;}
    public integer alllines{get;set;}
    public integer PercentageCovered{get;set;}
    public static string SortBy{get;set;}
    public CoverageWrap cw {get;set;}  
    public string ress{get;set;}  
    public CodeCoverageController(){
        //map<string,list<string>> testmap= TestClassesMap.getTestClassesMap();
        decimal allc=0;
        decimal allunc=0;
        decimal all=0;
        PercentageCovered=0;
        //map<string,list<string>> testmap = TestClassesMap.TestClassList(classesnames);
        HttpRequest req = new HttpRequest();
        req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
        req.setHeader('Content-Type', 'application/json');
        req.setEndpoint(URL.getSalesforceBaseURL().toExternalForm()+'/services/data/v33.0/tooling/query/?q=Select+id,ApexClassorTrigger.Name,NumLinesCovered,NumLinesUncovered+from+ApexCodeCoverageAggregate+ORDER+BY+NumLinesUncovered+DESC');
        req.setMethod('GET');
        Http h = new Http();
        HttpResponse res = h.send(req);
        if(res.getStatusCode() == 200){
            cw  = (CoverageWrap)JSON.deserialize(res.getBody(),CoverageWrap.class);
        }
        ress=res.getBody();
        integer i=0;
        cclist=new list<records>{};
        cctop5=new list<records>{};
        for(Records r:cw.records){
            if(r.NumLinesCovered+r.NumLinesunCovered!=0){
                //r.body=BodyMap.get(r.ApexClassOrTrigger.name);
                r.index='cls'+i;
                i++;
                r.TotalLines=r.NumLinesCovered+r.NumLinesunCovered;
                decimal d1=r.NumLinesCovered;
                allc=allc+d1;
                decimal d2=r.TotalLines;
                allunc=allunc+d2;
                decimal d=math.round((d1/d2)*100); 
                r.percentage=d.intvalue();
                if(r.percentage>=75)
                    r.colorcode='#82e0aa';
                else if(r.percentage>=50)
                    r.colorcode='#f8c471';
                else
                    r.colorcode='#f5b7b1';
                //r.testclasses=testmap.get(r.ApexClassOrTrigger.name);
                //r.testclasses=testmap.get(r.ApexClassOrTrigger.name);
                cclist.add(r);
                if(i<11)
                    cctop5.add(r);
            }
            all=allc+allunc;
            alllines=all.intvalue();
            if(all>0)
                PercentageCovered=(math.round((allc/allunc)*100));
            string sname='';
            if(PercentageCovered>=80){
                imgurl='warninggreen';
                cssclass='success';
            }
            else if(PercentageCovered>=75){
                imgurl='warningyellow';
                cssclass='warning';
            }

            else{
                imgurl='warningred';
                cssclass='danger';
            }
            //imgurl = [select URL from StaticResource where Name = :sname LIMIT 1].URL;
            allcovered=allc.intvalue();
            alluncovered=allunc.intvalue();   
        }
        SortBy='PercentDesc';
        //cclist.sort();
        list<string> d=new list<string>{};

    }

    public void execute(SchedulableContext obj){
        if(PercentageCovered>0)
        {
            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            OrgWideEmailAddress owe = [SELECT ID,IsAllowAllProfiles,DisplayName,Address FROM OrgWideEmailAddress WHERE Address='noreply@maids.ae'];
            String[] sentTo = new String[]{'riad.magnamedia@gmail.com','aliabdullah.magna@gmail.com'};
            String subject='';
            string msg=''; 
            string bg='';
            if(PercentageCovered>75){
                subject = 'Warning! Code Coverage Percentage(75 to 80)%';
                msg='<h1 style="padding:20px;text-align:center;color:white;background-color:orange">Warning! Code Coverage Percentage is : '+PercentageCovered+'%</h1>';
                bg=' lightgrey ';
            }
            else{
                subject = 'Critical! Code Coverage Percentage Less Than 75%';
                msg='<h1 style="padding:20px;text-align:center;color:white;background-color:#ff6565">Critical! Code Coverage Percentage is : '+PercentageCovered+'%</h1>';
                bg='lightgrey';
            }
            mail.setToAddresses(sentTo);
            mail.setOrgWideEmailAddressId(owe.Id);
            mail.setSubject(subject);
            mail.setBccSender(false);
            mail.setUseSignature(false);
            String body = '<html><head></head><body style="webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;'+
                          '-ms-flex-align:center;align-items:center;width:100%;">'+
                          '<div style="font-family:Arial, Helvetica, sans-serif;text-align:center;"><br/><br/><br/>';
            body+=msg;
            body+='<br/>';
            body += '<h2><u>Top 10 UnCovered Classes That Affects the Overall Code Coverage</u></h2>'+
                        '<table align="center" style="border: solid 2px #000;border-collapse:collapse;text-align:center;vertical-align:middle;">'+
                        '<thead style="padding:10px;background-color:'+bg+';font-weight:bold;text-align:center;font-size:18px;">'+
                        '<th style="border: solid 2px #000;padding:3px;">Apex Class Name</th>'+
                        '<th style="border: solid 2px #000;padding:3px;">Total Lines</th>'+
                        '<th style="border: solid 2px #000;padding:3px;">UnCovered Lines</th>'+
                        '</thead><tbody style="text-align:center;font-size:16px;">';

            for(records w : cctop5){
                    if(w != null){
                        body +='<tr><td style="border: solid 1px #000;padding:3px 10px;">'+ w.apexclassortrigger.name +'</td>';
                        body +='<td style="border: solid 1px #000;padding:3px 10px;">'+ w.totallines +'</td>';
                        body +='<td style="border: solid 1px #000;padding:3px 10px;">'+ w.NumLinesUncovered +'</td>';
                        body +='</tr>';
                }
            }
            body+='</tbody></table>'; 
            body+='</div></body></html>';
            mail.setHtmlBody(body);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

        }
    }


    public PageReference SortByTotalLines(){
        SortBy='TotalDesc';
        cclist.sort();
        return null;
    }


    public PageReference SortByPercent(){
        SortBy='PercentDesc';
        cclist.sort();
        return null;
    }

    public list<records> cclist{get;set;}
    public list<records> cctop5{get;set;}

    public class Attributes {
        public String type;
        public String url;
    }

    public class Records implements Comparable{
        public Attributes attributes;
        public String Id{get;set;}
        public ApexClassOrTrigger ApexClassOrTrigger {get;set;}
        public Integer NumLinesCovered {get;set;}
        public Integer NumLinesUncovered {get;set;}
        public Integer TotalLines {get;set;}
        public string  Body{get;set;}
        public string index{get;set;}
        public integer percentage{get;set;}
        public string colorcode{get;set;}
        public list<string> testclasses{get;set;}

        public Integer compareTo(Object compareTo) {
            Records cmp = (Records)compareTo;
            if (CodeCoverageController.SortBy=='PercentDesc'){
                return (percentage<cmp.percentage ? 1 : -1);       
            } else if (CodeCoverageController.SortBy=='PercentAsc') {
                return (percentage>cmp.percentage ? -1 : 1) ; 
            }else if (CodeCoverageController.SortBy=='TotalDesc'){
                return (TotalLines<cmp.TotalLines ? 1 : -1);      
            } else if (CodeCoverageController.SortBy=='TotalAsc') {
                return (TotalLines>cmp.TotalLines ? 1 : -1) ;  
            } else if (CodeCoverageController.SortBy=='TotalUncDESC') {
                return (NumLinesUncovered<cmp.NumLinesUncovered ? 1 : -1) ;  
            }
            return -1;
        } 
    } 

    public class ApexClassOrTrigger {
        public Attributes attributes;
        public String Name{get;set;}
    }

    public class CoverageWrap{
        public Integer size;
        public Integer totalSize;
        public Boolean done;
        public Object queryLocator;
        public String entityTypeName;
        public List<Records> records{get;set;}
    }

    public List<string> classesNames{
        get{
            list<string> c=new list<string>{};
            if(classesNames==null){ 
                for(ApexClass cls : [Select name,body From ApexClass Where NamespacePrefix=null]){
                    c.add(cls.name);
                }
            }
            return c;
        }
    }

    public static map<string,string> BodyMap{
        get{
            if(BodyMap==null){
                BodyMap=new map<string,string>();
                for(ApexClass cls : [Select name,body From ApexClass Where NamespacePrefix=null]){
                    BodyMap.put(cls.name,cls.body);
                }

            } 
            return BodyMap;
        }
        set;
    }

    WebService static String getBody(String ClassName) {
        ApexClass cls=[Select name,body From ApexClass Where Name=:ClassName LIMIT 1];
        return cls.body;
    }

    WebService static String runalltests() {

        return testutil.enqueueTests();
    }

    public PageReference rr(){
        return null;
    }

}
  • 1
    Please seeHow to Ask on getting the most from the community. There's way too much code dumped here. Tighten up your question using edit to the essential bits only – cropredy Nov 1 '16 at 18:07
1

UserInfo.getSessionId() isn't available in scheduled Apex.

You either need to pass a valid session ID in (How to get UserInfo.getSessionId() in Scheduler/Batch) or establish a session within the Scheduled Apex (Session ID from scheduled jobs).

The latter seems like a better approach for you as a passed in session would likely expire before it is used.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.