Monday 29 October 2018

Apex: Creating CRON Expression dynamically from VF page


http://faizanaz90.blogspot.com/2016/03/apex-creating-cron-expression.html

+++++++++++

CRON Expression:

A command to an operating system or server for a job that is to be executed at a specified time.

CRONTrigger:

An object that contains schedule information for a schedule job.This object contain all the information related to any schedule job in your organization. Read More Here!

Visualforce Page for Dynamic CRON Creation:

The use case this page covers is when users want to schedule  a class from VF page.User have choice to set schedule date and time according to his convenience from any day of week.

We will be using Multiselect picklist to show days of weeks as user might want to schedule it for more than 1 day.



We will use single select picklist in order to capture preferred time from user.


VF Page Code:

     <apex:pageBlock id="pb4">
            <apex:pageBlockSection title="Frequency" id="pbs10" collapsible="false" 
             columns="1">
            
                <apex:selectList label="Recurs Every Week On" multiselect="true"  
                 size="5" id="FrequencyWeekly" value="{!SelectedFreqValue}">
                    <apex:selectOptions value="{!OppWeekDays}"  />
                       
                </apex:selectList>
               
                <apex:selectList label="Preferred Start Time" multiselect="false"  
                 size="1" id="Time" value="{!SelectedTime}">

                    <apex:selectOptions value="{!FrequencyTime}"/>
                </apex:selectList>
                    
                <apex:outputLabel styleclass="labelCol vfLabelColTextWrap" 
                 value="Exact time will be dependent on Job queue activity" 
                 style="text-align:left !important; font-size: 10px !important;"/>
            </apex:pageBlockSection>
            
        </apex:pageBlock>

Controller Class Code

//Defining Properties for capturing Frequency
    public String SelectedFreqValue {get;set;} 
    public string SelectedTime {get;set;}

//Defining List of selectoption
public List<selectOption> OppWeekDays{get;set;}
 public List<selectoption> FrequencyTime{get;set;}

/****************************************************getFrequencyTime**********************************/
    //get frequency time
    public List<selectOption> getFrequencyTime(){
        
        FrequencyTime = new List<selectoption>();
        
        FrequencyTime.add(new selectOption('0',Constants.CONST_TWELVE_AM));
        FrequencyTime.add(new selectOption('1',Constants.CONST_ONE_AM));
        FrequencyTime.add(new selectOption('2',Constants.CONST_TWO_AM));
        FrequencyTime.add(new selectOption('3',Constants.CONST_THREE_AM));
        FrequencyTime.add(new selectOption('4',Constants.CONST_FOUR_AM));
        FrequencyTime.add(new selectOption('5',Constants.CONST_FIVE_AM));
        FrequencyTime.add(new selectOption('6',Constants.CONST_SIX_AM));
        FrequencyTime.add(new selectOption('7',Constants.CONST_SEVEN_AM));
        FrequencyTime.add(new selectOption('8',Constants.CONST_EIGHT_AM));
        FrequencyTime.add(new selectOption('9',Constants.CONST_NINE_AM));
        FrequencyTime.add(new selectOption('10',Constants.CONST_TEN_AM));
        FrequencyTime.add(new selectOption('11',Constants.CONST_ELEVEN_AM));
        FrequencyTime.add(new selectOption('12',Constants.CONST_TWELVE_PM));
        FrequencyTime.add(new selectOption('13',Constants.CONST_ONE_PM));
        FrequencyTime.add(new selectOption('14',Constants.CONST_TWO_PM));
        FrequencyTime.add(new selectOption('15',Constants.CONST_THREE_PM));
        FrequencyTime.add(new selectOption('16',Constants.CONST_FOUR_PM));
        FrequencyTime.add(new selectOption('17',Constants.CONST_FIVE_PM));
        FrequencyTime.add(new selectOption('18',Constants.CONST_SIX_PM));
        FrequencyTime.add(new selectOption('19',Constants.CONST_SEVEN_PM));
        FrequencyTime.add(new selectOption('20',Constants.CONST_EIGHT_PM));
        FrequencyTime.add(new selectOption('21',Constants.CONST_NINE_PM));
        FrequencyTime.add(new selectOption('22',Constants.CONST_TEN_PM));
        FrequencyTime.add(new selectOption('23',Constants.CONST_ELVEN_PM));
        
        return FrequencyTime;
    }


/*************************************************getOppWeekDays****************************************/
    //get renewal opp week days list
    public List<SelectOption> getOppWeekDays(){
        
        OppWeekDays = new List<selectoption>();
        
        OppWeekDays.add(new selectOption('SUN',CONST_SUNDAY));
        OppWeekDays.add(new selectOption('MON',CONST_MONDAY));
        OppWeekDays.add(new selectOption('TUES',CONST_TUESDAY));
        OppWeekDays.add(new selectOption('WED',CONST_WEDNESDAY));
        OppWeekDays.add(new selectOption('THUR',CONST_THURSDAY));
        OppWeekDays.add(new selectOption('FRI',CONST_FRIDAY));
        OppWeekDays.add(new selectOption('SAT',CONST_SATURDAY));
        
        return OppWeekDays;
    }

Create a constant class where you can add all times you want to show on page.Like i create a 
class name "Constant" and add times from "12 AM" till "11 PM" and names of days from Sunday till Saturday.


CRON Creation Method


public string GetCronStringForSchedule(){
        Integer Schdtime = Integer.valueOf(SelectedTime);
         string sch = '';
            string a = '';
            SelectedFreqValue= SelectedFreqValue.replaceAll( '\\s+', '');
            SelectedFreqValue = SelectedFreqValue.remove(')');
            SelectedFreqValue = SelectedFreqValue.remove('(');
            List<String> ListOfValues = SelectedFreqValue.split('\\,');
            if(ListOfValues.size() >0)
                a = ListOfValues.get(0)+ '-' + ListOfValues.get(ListOfValues.size()- 1);
            else
                a = ListOfValues.get(0);
            sch = '0 0 '+ Schdtime +' ? * '+ a;
    }

public string JobSchedular(){
string sch = GetCronStringForSchedule();
      string  jobID = system.schedule(BATCH_JOB_NAME, sch, batchjob);
return jobID;
}

Save this job ID some where so you can re use it in future if you want to abort this job from page.

Hope this helps you. Happy Coding !!

Tuesday 23 October 2018

24th_OCT

*********

/*
    Name               : AutomatedTestSetup_Controller
    Test class         : AutomatedTestSetup_Controller_Test
    Description        : For Automated Test class execution process(SP-684-Automate Test Classes execution in Salesforce Orgs)
    Created By         : Krishna yerru
    Created Date       : 23-Oct-2018

********************************************************************************************************************************
    Change Version   Name              Date                    Task/Case#                 Description
********************************************************************************************************************************

********************************************************************************************************************************     
*/


public with sharing class AutomatedTestSetup_Controller {

    public boolean hasScheduledJobs { get; set; }
    public boolean hasAbort { get; set; }
    public boolean hasemailpending { get; set; }
    public boolean isRunning { get; set; }
    public boolean isEmailing { get; set; }
    //public boolean isEmailReq { get; set; }
    public AutomatedTestSetup_Controller ATS { get; set; }
    public String DtValue {get; set; }
    public boolean showMessage {get;set;}
    public String showdatetime{get;set;}
    public String Staticstics{get;set;}
    public Decimal Percentage{get;set;}
    public String shddatetime {get;set;}
    public String ATRdetails {get;set;}
public String PastATRdetails {get;set;}
    public List<CronTrigger> Schdjobs{get;set;}
    public String Jobstatus  {get;set;}
    public Automated_Test_Run__c AtrRecord  {get; set;}
    //public List<Shdwrapper> cronjbs=New List<Shdwrapper>(){get;set;}
     id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
     id ATEmailRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
    public PageReference doInsert() {
       // Automated_Test_Run__c objdlt = new Automated_Test_Run__c();
       List<Automated_Test_Run__c> ATSrecrdsinsert=New List<Automated_Test_Run__c>();
        AtrRecord.Query__c=AtrRecord.Query__c;
        AtrRecord.Excluded_Classes__c=AtrRecord.Excluded_Classes__c;
        AtrRecord.Exclude_Managed_Packages__c=AtrRecord.Exclude_Managed_Packages__c;
        AtrRecord.Schedule__c=AtrRecord.Schedule__c;
       
        AtrRecord.RecordTypeId=ATERecordTypeId;
        ATSrecrdsinsert.add(AtrRecord);
       
        Automated_Test_Run__c ATEemail = new Automated_Test_Run__c();
ATEemail.Query__c=AtrRecord.Query__c;
        ATEemail.Emails__c=AtrRecord.Emails__c;
        ATEemail.Email_on_Pass__c=AtrRecord.Email_on_Pass__c;
        ATEemail.RecordTypeId=ATEmailRecordTypeId;
        ATSrecrdsinsert.add(ATEemail);
        Savepoint sp = Database.setSavepoint();
        try{     
            scheduleJobs(AtrRecord.Schedule__c);
                if(showMessage==false){
                    upsert ATSrecrdsinsert;               
                }     
        }
        catch(exception ex){
            Database.rollback(sp);
        }
        GetATSRunDeatils();
       /*PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
            pageRef.setRedirect(true);
            return pageRef;*/
            return null;
    }
    public Automated_Test_Run__c getAtrRecord()
    {
        return AtrRecord;
    }
   
   
    public AutomatedTestSetup_Controller(ApexPages.StandardController controller) {
        //Automated_Test_Run__c AtrRecord = new Automated_Test_Run__c();//from
        AtrRecord = (Automated_Test_Run__c)Controller.getRecord();
        this.ATS=ATS; 
       
        showMessage=false;
        refreshHasScheduledJobs();
        //refreshHasTestRun();
        ShowAbortbutton();
        getPieData();
        Calculatepercentage();
        GetATSRunDeatils();
        EmailSendPending();   
    }
   
   

    public void refreshHasScheduledJobs() {     
        integer jobCount = [SELECT count() FROM CronTrigger  where CronJobDetail.Name like '%TestRunner%'];
        Schdjobs=[SELECT CronJobDetail.Name,CreatedDate,NextFireTime,State FROM CronTrigger where CronJobDetail.Name like '%TestRunner%' and State in('WAITING','ACQUIRED','EXECUTING')];
        if(Schdjobs.size()>0){
            Jobstatus=Schdjobs[0].State;
            if(Schdjobs[0].NextFireTime!=null ){
            Datetime shddatetimeGSt=Schdjobs[0].NextFireTime;
            Datetime gmt = shddatetimeGSt;
             String timeZone = UserInfo.getTimeZone().getID();
             Datetime GivenDateTime=shddatetimeGSt;// here you can user your dates e.g. createddate
              Datetime localdt=Datetime.valueOf(GivenDateTime);
              //showdatetime = string.valueOfGmt(local);
              shddatetime=localdt.format();
              }
              else if(Jobstatus!=null && Jobstatus!='') {
                  shddatetime='Test Scheduled Job Current State is '+Jobstatus;
              }
            }           
        hasScheduledJobs = jobCount !=0;
        //hasScheduledJobs = (jobCount !=0 && Schdjobs.size()>0);         
            /*if(jobCount !=0){
                hasScheduledJobs = jobCount !=0;
            }else if(Schdjobs.size()>0){
            hasScheduledJobs =true;
            } */           
    }
    public void GetATSRunDeatils() {
        List<String> Keywords=New List<String>();
        Keywords.clear();
        ATRdetails='';
        for(Automated_Test_Run__c atr: [select Query__c, Excluded_Classes__c,
                            Email_on_Pass__c, Exclude_Managed_Packages__c
                            from Automated_Test_Run__c
                            where Active__c = true and RecordTypeId=:ATERecordTypeId order by createdDate DESC limit 1]){
                        Keywords.add(atr.Query__c);                     
        }
        if(Keywords.size()>0){
            for(String kw:Keywords){
            ATRdetails+=kw;
            }
        }
    }

    public void ShowAbortbutton(){
        integer runCount = [select count() from Automated_Test_Run__c limit 1];
        List<Test_Runner_Job__c> RunningJobnm =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
        if(RunningJobnm.size()>0){
            integer TestexecrunCount = [select count() from ApexTestQueueItem WHERE Status IN ('Holding','Queued','Preparing','Processing') and ParentJobId=:RunningJobnm[0].Name];
            hasAbort = TestexecrunCount > 0;
            //hasScheduledJobs = TestexecrunCount > 0;     
         }     
    }
   
    public void EmailSendPending(){
        List<Test_Runner_Job__c> runCountJob = [select id from Test_Runner_Job__c where Processed__c=false order by CreatedDate desc limit 1];
        hasemailpending = runCountJob.size()> 0;
        //hasScheduledJobs = TestexecrunCount > 0;                   
    }
 
    public string getTestRunLink() {
        return '/' + Automated_Test_Run__c.SObjectType.getDescribe().getKeyPrefix();
    }
 
    public AutomatedTestSetup_Controller() {
         Automated_Test_Run__c AtrRecord = new Automated_Test_Run__c();
         refreshHasScheduledJobs();
         Calculatepercentage();
         ShowAbortbutton();
         EmailSendPending();
    }
   
    public PageReference scheduleJobs(Datetime DtValue) {
       
        System.debug('Date & Time is given***1'+DtValue);
        deleteCompletedJobs();
        Datetime gmt = DtValue;
        String timeZone = UserInfo.getTimeZone().getID();
        Datetime GivenDateTime=DtValue;// here you can user your dates e.g. createddate
         System.debug('GivenDateTime is***'+GivenDateTime);         
                Datetime local=Datetime.valueOf(GivenDateTime);
                System.debug('local is***'+local);
                Map <Integer,String> monthNumbers = new Map <Integer,String> {1=>'Jan', 2=>'Feb',3=>'Mar',4=>'Apr', 5=>'May', 6=>'Jun',7=>'Jul',8=>'Aug', 9=>'Sep', 10=>'Oct', 11=>'Nov', 12=>'Dec'};
                String TestShdmonth=monthNumbers.get(local.month());
                String strSchedule = '0 ' + local.minute() + ' ' +local.hour()+ ' ' + local.day()+ ' ' + TestShdmonth+ ' ? ' + ' ' + local.year();
                System.debug('***strSchedule***'+strSchedule);
                AutoTestRunner.setup(strSchedule);
                refreshHasScheduledJobs();             
         
       
    return null;
    }

    public PageReference CancelJobs() {   
          //List<CronTrigger> jobsToAbort = [select id,Name from CronJobDetail where Name like 'AutoTestRunner%' and JobType = '7'];
          List<CronTrigger> jobsToAbort = [select Id from CronTrigger where CronJobDetail.JobType = '7' and CronJobDetail.Name like '%TestRunner%'];
              if(jobsToAbort.size()>0){
                  for (CronTrigger job : jobsToAbort) {
                   System.abortJob(job.Id);
                   }
               }
               PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
                    pageRef.setRedirect(true);
                    return pageRef;
    }
   
    public PageReference AbortTestJobs() {
            //isEmailReq=True;   
        Test_Runner_Job__c RunningJobnm =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
        ApexTestQueueItem[] items = [SELECT Id FROM ApexTestQueueItem WHERE Status IN ('Holding','Queued','Preparing','Processing') and ParentJobId=:RunningJobnm.Name];
        if(items.size()>0){
                for(ApexTestQueueItem item: items) {
                    item.Status = 'Aborted';
                }
                update items;
           }
         email();
        PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
        pageRef.setRedirect(true);
        return pageRef;
    }
   
    public void deleteCompletedJobs(){
        List<CronTrigger> jobsToAbort = [select Id,State from CronTrigger where CronJobDetail.JobType = '7' and CronJobDetail.Name like '%TestRunner%' and State='DELETED'];
              for (CronTrigger job : jobsToAbort) {
               System.abortJob(job.Id);
               }     
    }

    public void email() {
        //TestRunnerResults.emailUnprocessedJobStatus();
        emailUnprocessedJobStatus();
        isEmailing = true;
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.Confirm, 'Results processed and emailed'));
    }
   
    public static list<Messaging.SingleEmailMessage> emailUnprocessedJobStatus() {
          list<Test_Runner_Job__c> jobs = getUnprocessedJobs();     
          //list<Messaging.SingleEmailMessage> messages = AutoTestRunner.emailMethodStatus(jobs);
          list<Messaging.SingleEmailMessage> messages =emailMethodStatus(jobs);     
              for (Test_Runner_Job__c job : jobs) {
                  job.Processed__c = true;
              }     
          update jobs;   
         return messages;
    }
 
   public static list<Test_Runner_Job__c> getUnprocessedJobs() {
        return [Select t.Name,
          t.Automated_Test_Run__r.Emails__c,
          t.Automated_Test_Run__r.Email_on_Pass__c,
          t.Automated_Test_Run__r.Name,
          t.Automated_Test_Run__c
          From Test_Runner_Job__c t where Processed__c = false];
   }
 
//Statistics part

    public Void Calculatepercentage() {
PastATRdetails='';
        List<Test_Runner_Job__c> RunningJob =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
        if(RunningJob.size()>0){
Automated_Test_Run__c PastATR=[select id,Query__c from Automated_Test_Run__c where id=:RunningJob[0].Automated_Test_Run__c order by createdDate DESC limit 1];
            PastATRdetails=PastATR.Query__c;
integer TotalJobsis   =  [select count() FROM ApexTestQueueItem where ParentJobId=:RunningJob[0].Name];
            integer CompltedJobsis   =  [select count() FROM ApexTestQueueItem where Status IN ('Completed','Aborted') and ParentJobId=:RunningJob[0].Name];
                if((TotalJobsis>0)&& (CompltedJobsis>0)){
                Percentage=(CompltedJobsis*100)/TotalJobsis;
                System.debug('Total Jobs is'+TotalJobsis+ 'CompltedJobs' +CompltedJobsis+ 'Percentage is'+Percentage);
            }         
        }     
    }
    public List<PieWedgeData> getPieData() {
        List<PieWedgeData> data = new List<PieWedgeData>();   
        List<Test_Runner_Job__c> RunningJob =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
              if(RunningJob.size()>0){
                  //integer Cmpltd       = [select count() FROM ApexTestResult WHERE Outcome = 'Pass' and AsyncApexJobId=:RunningJob[0].Name];
                  integer CmpltdPass       = [select count() FROM ApexTestResult WHERE Outcome = 'Pass' and AsyncApexJobId=:RunningJob[0].Name];
                  integer Failed       = [select count() FROM ApexTestResult WHERE Outcome = 'Fail' and AsyncApexJobId=:RunningJob[0].Name];
                  integer Queuedjobs   = [select count() FROM ApexTestQueueItem where Status='Queued' and ParentJobId=:RunningJob[0].Name];
                  integer TotalJobs   =  [select count() FROM ApexTestQueueItem where ParentJobId=:RunningJob[0].Name];
                 
                        if(Queuedjobs>0){
                        data.add(new PieWedgeData('In Progress'+' '+Queuedjobs, +Queuedjobs));
                        }if(CmpltdPass>0){
                        data.add(new PieWedgeData('Passed'+' '+CmpltdPass, +CmpltdPass));
                        }if(Failed>0){
                        data.add(new PieWedgeData('Fail'+' '+Failed, +Failed));
                        }
               } 
        return data;
    }
    // Wrapper class
    public class PieWedgeData {
       public String name { get; set; }
       public Integer data { get; set; }
       public Integer CmpltdPass{ get; set; }
       public Integer Failed{ get; set; }
       public Integer Queuedjobs{ get; set; }
           public PieWedgeData(String name, Integer data) {
                this.name = name;
                this.data = data;
            }
    }
   
    public PageReference Refresh(){
        deleteCompletedJobs();
        Calculatepercentage();
        refreshHasScheduledJobs();
        if(Percentage==100){
                email();                   
            }else{
                hasScheduledJobs = true;
            }                     
        PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
        pageRef.setRedirect(true);
        return pageRef;
    }
    //Scheduling Job run & Email Sending from Auotestrunner class
    // Enqueue all unit test classes as spec'd by Automated_Test_Run__c record(s)
   
    public static list<ID> enqueueTests() {
        list<Id> jobIds = new list<Id>();
        Id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
        Id ATEmilRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
        Automated_Test_Run__c EmailRecord=[select Emails__c from Automated_Test_Run__c where RecordTypeId=:ATEmilRecordTypeId  order by createdDate DESC limit 1];
        string whereExcluded = '';
        string Keywordis = '';
        string ATRIDis = '';
        for (Automated_Test_Run__c run : [select Query__c, Excluded_Classes__c,
            Email_on_Pass__c, Exclude_Managed_Packages__c
            from Automated_Test_Run__c where Active__c = true and RecordTypeId=:ATERecordTypeId order by createdDate DESC limit 1]) {
               ATRIDis=run.id;
                if (run.Excluded_Classes__c != null) {
                    for (string c : run.Excluded_Classes__c.split('[,\\s]+')) {
                        whereExcluded += 'and Name != \'' + c + '\'';
                    }
                }
                if (run.Exclude_Managed_Packages__c == True) {
                   whereExcluded += ' AND NameSpacePrefix = null';
                }
                if (run.Query__c != null && run.Query__c != ' ' ) {
                   Keywordis +=run.Query__c;
                }
           }
            string query = 'SELECT Id FROM ApexClass WHERE Name LIKE \'' + Keywordis+ '\' ' + whereExcluded;
            ApexClass[] testClasses = Database.query(query);
             
            if (testClasses.size() > 0) {
                ApexTestQueueItem[] queueItems = new List<ApexTestQueueItem>();
                for (ApexClass cls : testClasses) {
                    queueItems.add(new ApexTestQueueItem(ApexClassId=cls.Id));
                } 
                if (!Test.isRunningTest()) {
                    DataBase.insert(queueItems,false);     
                    // Get the job ID of the first queue item returned.       
                    ApexTestQueueItem item =[SELECT ParentJobId FROM ApexTestQueueItem WHERE Id=:queueItems[0].Id LIMIT 1];                   
                    insert new Test_Runner_Job__c(Name = item.parentjobid, Automated_Test_Run__c = EmailRecord.Id);
                    jobIds.add(item.parentjobid);
                if(ATRIDis!='' && ATRIDis!=null){
                        Automated_Test_Run__c runATRrecd =[select id,Active__c from Automated_Test_Run__c where Id=:ATRIDis limit 1];
                           runATRrecd.Active__c = false;
                           update runATRrecd;
                   }
                   
                }
            }           
        return jobIds;
    }

    public static list<Messaging.SingleEmailMessage> emailMethodStatus(list<Test_Runner_Job__c> jobs) {
        set<string> jobNames = new set<string>();
        for (Test_Runner_Job__c job : jobs) {
            jobNames.add(job.Name);
        }     
        ApexTestResult[] results = [SELECT AsyncApexJobId, Outcome, ApexClass.Name, MethodName, Message, StackTrace
                                    FROM ApexTestResult
                                    WHERE AsyncApexJobId in :jobNames];
         
        return emailMethodStatus(jobs, results);
    }
     
    public static list<Messaging.SingleEmailMessage> emailMethodStatus(list<Test_Runner_Job__c> jobs, ApexTestResult[] results) {
        list<Messaging.SingleEmailMessage> messages = new list<Messaging.SingleEmailMessage>();
     
        for (Test_Runner_Job__c job : jobs) {
            system.debug('Test Runner Job: Id ' + job.Id + ' Name ' + job.Name);
            integer passed = 0;
            integer total = 0;
         
            string failTable = '<table border="1" cellpadding="5px">';
            string className = '';
             
            for (ApexTestResult atr : results) {
                system.debug('Apex Test Result: Id '  + atr.AsyncApexJobId);
                if ((string)atr.AsyncApexJobId == job.Name || (Test.isRunningTest() && jobs.size() == 1)) {
                    if (atr.Outcome == 'Pass') {
                        passed++;
                    } else {
                        if (atr.ApexClass.Name != className) {
                            className = atr.ApexClass.Name;
                            failTable += '<tr style="background: #ddd; font-weight: bold;"><td colspan="2">' + className + '</td></tr>\n';
                        }
                        failTable += '<tr><td>' + atr.MethodName + '</td><td> ' + atr.message + '</td></tr>\n';
                    }
                    total++;
                }
            }
         
            failTable += '</table>';
         
            string body = '<p>' + passed + '/' + total + ' tests passed</p>\n';
            boolean allPassed = passed == total;
         
            if (!allPassed) {
                body += '<p>Test Failures:</p>\n' + failTable;
            }
         
            if ((allPassed && job.Automated_Test_Run__r.Email_on_Pass__c) || !allPassed) {
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                mail.setToAddresses(job.Automated_Test_Run__r.Emails__c.split('[,\\s]+'));
                mail.setSubject(job.Automated_Test_Run__r.Name + ' Automated Test Results: ' + (passed < total ? 'Fail' : 'Pass'));
                mail.setHtmlBody(body);
                System.debug(mail);
                messages.add(mail);
            }
        }   

        if (!Test.isRunningTest()) {
            Messaging.sendEmail(messages);
        }
     
        return messages;
    }
   
}


****************

<!--*************************************************************************           
             
    Page Name          : AutomatedTestSetup
    Description        : For Automated Test class execution process(SP-684-Automate Test Classes execution in Salesforce Orgs)
    Created By         : Krishna yerru
    Created Date       : 23-Oct-2018

********************************************************************************************************************************
    Change Version   Name              Date                    Task/Case#                 Description
********************************************************************************************************************************

******************************************************************************************************************************** 
*************************************************************************/-->

<apex:page standardController="Automated_Test_Run__c" extensions="AutomatedTestSetup_Controller" Sidebar="False" id="pg" docType="html-5.0">

    <apex:form id="frm">
     
     <apex:pageBlock title="Job Schedule - Test Execution">
       <apex:pageMessages />
   <br/>
  <div align="right" draggable="false" >
   <apex:outputLink style="font-weight:bold;font-size:13px;float:Right;" value="{!testRunLink}">Scheduled Jobs History</apex:outputLink>
   </div>
<br/><br/>
        <!--Automated Test Record-->
<apex:outputPanel rendered="{!if(NOT(hasScheduledJobs) && Not(hasAbort) && Not(hasemailpending),true,false)}">

<apex:pageBlockSection title="Automated Test Run" columns="2">         
<apex:pageBlockSectionItem helpText="Test class names containing this value would be considered for automated test execution Ex:Test% or %_Test (case insensitive)">
  <apex:outputLabel value="Keyword"/>
  <apex:inputField required="true" value="{!AtrRecord.Query__c}" label="Keyword"/>               
</apex:pageBlockSectionItem>
 
<apex:pageBlockSectionItem helpText="Comma-delimited list of classes to exclude from testing">
   <apex:outputLabel value="Excluded Classes"/>                   
   <apex:inputField value="{!AtrRecord.Excluded_Classes__c}" label="Excluded Classes"/>
</apex:pageBlockSectionItem>

<apex:pageBlockSectionItem helpText="Check this box to exclude all Managed Package Unit Tests">
<apex:outputLabel value="Exclude Managed_Packages"/> 
<apex:inputField value="{!AtrRecord.Exclude_Managed_Packages__c}" label="Exclude Managed_Packages"/>                 
</apex:pageBlockSectionItem>                   
</apex:pageBlockSection>

<apex:pageBlockSection title="Automated Test Email" columns="2">

<apex:pageBlockSectionItem helpText="Comma-separated email addresses">
<apex:outputLabel value="Email"/>
<apex:inputField required="true" value="{!AtrRecord.Emails__c}" label="Email"/>
</apex:pageBlockSectionItem>   

<apex:pageBlockSectionItem helpText="Send email when all tests pass">
<apex:outputLabel value="Email on Pass"/>
<apex:inputField value="{!AtrRecord.Email_on_Pass__c}" label="Email on Pass"/>
</apex:pageBlockSectionItem>                   
</apex:pageBlockSection>

<apex:pageBlockSection title="Job Schedule " columns="1">
<apex:pageBlockSectionItem helpText="To Schedule Testclass Execution">
<apex:outputLabel value="Schedule Date and Time"/>
<apex:inputField required="true" value="{!AtrRecord.Schedule__c}" label="Schedule Date and Time"/>
<!--<c:AutomatedVFPHelpIcon helpText="To Schedule Testclass Execution"/>-->
</apex:pageBlockSectionItem>   

<apex:pageBlockSectionItem> 
<!--<div align="center" draggable="false" >--> 
<apex:commandButton value="Save & Submit" style="text-align: center" action="{!doInsert}" />
<!--</div>-->
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<!--Automated Test Record-->
</apex:outputPanel> 
                   
                   <!-- <apex:outputPanel rendered="{!hasScheduledJobs}">-->
                    <apex:outputPanel rendered="{!if(hasScheduledJobs && Not(hasemailpending),true,false)}">
                        <apex:pageBlockSection title="Job Schedule Status" columns="1">
                            Automated Test Run Name:{!ATRdetails}_TestRun_{!shddatetime}                                                         
                                <apex:commandLink value="Cancel" rendered="{!if(hasScheduledJobs && Not(hasAbort) && Not(hasemailpending),true,false)}" action="{!CancelJobs}" styleClass="btn">
                                </apex:commandLink>
                        </apex:pageBlockSection>
                    </apex:outputPanel>
                     <apex:outputPanel rendered="{!(hasAbort)}">
                        <apex:pageBlockSection title="Job Schedule Status" columns="1">
                            Automated Test Run Name:{!ATRdetails}_TestRun_In Progress                                                                                     
                        </apex:pageBlockSection>
                    </apex:outputPanel>
                   
                    <apex:outputPanel rendered="{!if(hasemailpending && Not(hasAbort),true,false)}" >
                   <!-- <apex:outputPanel rendered="{!(hasemailpending)}">-->
                        <apex:pageBlockSection title="Job Schedule Status" columns="1">
                            Automated Test Run Name:{!ATRdetails}_TestRun_Email Sent in Progress                                                                                     
                        </apex:pageBlockSection>
                    </apex:outputPanel>

                <!--Startstics Section -->
         
                <apex:pageBlockSection title="Test Class Execution Statistics" id="Piechartsec" columns="4">
                 <apex:pageBlockSectionItem>
TestRun Name:{!PastATRdetails}<div></div>
Testclass execution {!Percentage}% completed
  </apex:pageBlockSectionItem>
                    <apex:pageBlockSectionItem id="ShowGraph"> 
                        <apex:outputPanel id="Graph">
                                <apex:chart height="250" width="350" data="{!pieData}" id="Piechartsec2">
                                    <apex:pieSeries dataField="data" labelField="name"/>
                                    <apex:legend position="left"/>
                                </apex:chart>
                            </apex:outputPanel>                                                   
                    </apex:pageBlockSectionItem>               
                    <apex:pageBlockSectionItem id="Refresh">   
                        <apex:commandlink value=" Refresh " status="progress" action="{!Refresh}" styleClass="btn" reRender="Piechartsec2"/>
                        <!-- <apex:commandlink value=" Refresh " status="progress" onclick="window.location.reload();" styleClass="btn" reRender="Piechartsec2"/>-->
                    </apex:pageBlockSectionItem>

                    <apex:pageBlockSectionItem id="Abort">                   
                        <apex:commandButton value="Abort" status="progress" action="{!AbortTestJobs}" rendered="{!(hasAbort)}" onclick="return confirm('Are you sure to abort and get the current results in an email ?')" />
                <!--<apex:commandButton value="Abort"   rendered="{!(hasAbort)}"  onclick="return abortproc();"/>-->
                  </apex:pageBlockSectionItem>                   
                </apex:pageBlockSection>
      </apex:pageBlock>
    </apex:form>
</apex:page>
                 

*******************

/*
    Name               : AutomatedTestSetup_Controller_Test
    Apex class         : AutomatedTestSetup_Controller
    Description        : For Automated Test class execution process(SP-684-Automate Test Classes execution in Salesforce Orgs)
    Created By         : Krishna yerru
    Created Date       : 23-Oct-2018

********************************************************************************************************************************
    Change Version   Name              Date                    Task/Case#                 Description
********************************************************************************************************************************

********************************************************************************************************************************     
*/
@isTest
private class AutomatedTestSetup_Controller_Test {
    static Automated_Test_Run__c run;
    static Test_Runner_Job__c job;
    static list<Messaging.SingleEmailMessage> messages;
    static Messaging.SingleEmailMessage mail;
   
    static {
        Id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
        Id ATEmilRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
        DateTime dt = System.now();
        DateTime future = dt.addMinutes(+5);
        run = new Automated_Test_Run__c(Name = 'Test Automated Run', Excluded_Classes__c = 'TestRunner, Foo',Schedule__c=future,Emails__c = 'test@test.com',RecordtypeID=ATERecordTypeId);
        insert run;
       
        job = new Test_Runner_Job__c(Name = 'Test', Automated_Test_Run__c = run.Id);
        insert job;
       
        runJobs();
    }
   
    static void runJobs() {
        messages = AutomatedTestSetup_Controller.emailUnprocessedJobStatus();
        mail = messages.size() > 0 ? messages[0] : null;
    }     

    public static testMethod void emailCreatedForAllPassing() {
        Test.startTest();
        System.assert(mail.getSubject().contains(run.Name), 'Run name not in subject');     
        set<string> emails = new set<string>();
        emails.addAll(mail.getToAddresses());
        System.assert(emails.contains(run.Emails__c), 'Run emails not in mail');       
        System.assert(!mail.getHtmlBody().contains('Test Failures'), 'Failures appear for passing tests');
        Test.Stoptest();
    }
   
    public static testMethod void emailCreatedForFailures() {
        list<ApexTestResult> results = new list<ApexTestResult>();
        Test.startTest();
        ApexTestResult result = new ApexTestResult(AsyncApexJobId = job.Id, Outcome = 'Fail', ApexClass = [select Id, Name from ApexClass limit 1], MethodName = 'TestMethod', Message  = 'Test Message', StackTrace = 'Test Stack Trace');     
        results.add(result);
       
        list<Test_Runner_Job__c> jobs = [Select t.Name,
          t.Automated_Test_Run__r.Emails__c,
          t.Automated_Test_Run__r.Email_on_Pass__c,
          t.Automated_Test_Run__r.Name,
          t.Automated_Test_Run__c
          From Test_Runner_Job__c t where t.Id = :job.Id];
            mail = AutomatedTestSetup_Controller.emailMethodStatus(jobs, results)[0];           
        System.assert(mail.getHtmlBody().contains(result.Message), 'No message for failures'); 
        Test.Stoptest();       
    }
   
    public static testMethod void emailOnPassUnchecked() {
        Test.startTest();
        run.Email_on_Pass__c = false;
        update run;       
        job = job.clone();
        insert job;       
        runJobs();       
        System.assertEquals(null, mail, 'Email created when Email on Pass unchecked');
        Test.stopTest();
    }
   
    public static testMethod void testRunnerResultsProcessesJobs() {
        Test.startTest();
        job = [select Processed__c from Test_Runner_Job__c where Id = :job.Id];
        System.assert(job.Processed__c, 'Job not marked processed');
        Test.stopTest();
    }
   
    //newly
   
  public static testMethod void TestATSrecords() {
         Id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
        Id ATEmilRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
        DateTime dt = System.now();
        DateTime future = dt.addMinutes(+5);
        List<Automated_Test_Run__c> atsrecs=new List<Automated_Test_Run__c>();
        Automated_Test_Run__c  run1 = new Automated_Test_Run__c(Name = 'Test Automated Run', Excluded_Classes__c = 'TestRunner, Foo',Active__c = false,Emails__c = 'test@test.com',Schedule__c=future,RecordtypeID=ATERecordTypeId);
        atsrecs.add(run1);
        Automated_Test_Run__c run2 = new Automated_Test_Run__c(Name = 'Test Automated Run2',Emails__c = 'test@test.com',RecordtypeID=ATEmilRecordTypeId);
        atsrecs.add(run2);
        Test.startTest();
        insert atsrecs;   
        System.assert(atsrecs!=null);
        Test.stopTest();
    }

   
   
   
    static testMethod void testAutomatedprocess() {

        Id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
        Id ATEmilRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
        List<Automated_Test_Run__c> ATSList= New List<Automated_Test_Run__c>();
        DateTime dt = System.now();
        DateTime future = dt.addMinutes(+5);
        Automated_Test_Run__c  run1 = new Automated_Test_Run__c(Name = 'Test Automated Run',Query__c='%Test%', Excluded_Classes__c = 'TestRunner, Foo',Active__c = false,Emails__c = 'test@test.com',Schedule__c=future,RecordtypeID=ATERecordTypeId);
        ATSList.add(run1);
        Automated_Test_Run__c run2 = new Automated_Test_Run__c(Name = 'Test Automated Run2',Excluded_Classes__c = 'TestRunner, Foo',Emails__c = 'test@test.com',RecordtypeID=ATEmilRecordTypeId);
        ATSList.add(run2);
       
        Automated_Test_Run__c automated_test_run_Obj = new Automated_Test_Run__c(RecordTypeId = ATERecordTypeId,Active__c = false,Email_on_Pass__c = false, Emails__c = '18@test.com', Exclude_Managed_Packages__c = false, Excluded_Classes__c = '20', Query__c = 'Query__c828', Schedule__c = DateTime.now());
        ATSList.add(automated_test_run_Obj);
   
        Automated_Test_Run__c automated_test_run_Obj22 = new Automated_Test_Run__c(RecordTypeId = ATEmilRecordTypeId,Active__c = false,Email_on_Pass__c = false, Emails__c = '18', Exclude_Managed_Packages__c = false, Excluded_Classes__c = '20', Query__c = 'Query__c828', Schedule__c = DateTime.now());
        ATSList.add(automated_test_run_Obj22);
       
        test.startTest();
        insert ATSList;
        System.assert(ATSList!=null);
        PageReference pageRef = Page.AutomatedTestSetup;
        Test.setCurrentPage(pageRef);
        AutomatedTestSetup_Controller controller = new AutomatedTestSetup_Controller();
        AutomatedTestSetup_Controller.enqueueTests();
        Automated_Test_Run__c AtrRecord = new Automated_Test_Run__c();
        Controller.refreshHasScheduledJobs();
        Controller.getPieData();
        Controller.GetATSRunDeatils();
        Controller.Refresh();
        Controller.Calculatepercentage();
        Controller.ShowAbortbutton();
        Controller.EmailSendPending();
        Controller.email();
        DateTime dt2 = System.now();
        DateTime future2 = dt.addMinutes(+5);
        Controller.scheduleJobs(future);
        Controller.scheduleJobs(dt);
        Controller.CancelJobs();
        insert new Test_Runner_Job__c(Name = 'ParentJobid', Automated_Test_Run__c = run1.Id);
        Controller.AbortTestJobs();
        //Controller.AbortTestJobsEmailNotrequired();
        Controller.deleteCompletedJobs();
        Controller.getTestRunLink();
        test.StopTest();
       
}

public static testMethod void TestATSrecordinsertion() {
        Id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
        Id ATEmilRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
        DateTime dt = System.now();
        DateTime future = dt.addMinutes(+5);
        Automated_Test_Run__c AtrData= new Automated_Test_Run__c();
        AtrData.Name = 'Test Automated Run';
        AtrData.Query__c = '%Test%';
        AtrData.Excluded_Classes__c = 'TestRunner, Foo';
        AtrData.Active__c = false;
        AtrData.Emails__c= 'test@test.com';
        AtrData.Schedule__c = future;
        AtrData.RecordTypeId=ATERecordTypeId;
        test.startTest();         
        insert AtrData;
        system.assert(AtrData!=null);
        ApexPages.StandardController sc = new ApexPages.standardController(AtrData);
        AutomatedTestSetup_Controller e = new AutomatedTestSetup_Controller(sc);       
        AutomatedTestSetup_Controller sph = new AutomatedTestSetup_Controller (sc);
        PageReference pageRef = Page.AutomatedTestSetup;
        pageRef.getParameters().put('id', String.valueOf(AtrData.Id));
        Test.setCurrentPage(pageRef);
        sph.doInsert();
        test.StopTest();
}

}

****************

/*
    Name               : AutoTestRunner
    Test class         : AutomatedTestSetup_Controller_Test
    Description        : For Automated Test class execution process(SP-684-Automate Test Classes execution in Salesforce Orgs)
    Created By         : Krishna yerru
    Created Date       : 23-Oct-2018

********************************************************************************************************************************
    Change Version   Name              Date                    Task/Case#                 Description
********************************************************************************************************************************

********************************************************************************************************************************     
*/

global class AutoTestRunner implements Schedulable {
    public static void setup(String strSchedule) {
        try {
            String cronexpression=strSchedule;
            system.schedule('AutoTestRunner',cronexpression, new AutoTestRunner());
        } catch (Asyncexception ex) {
            system.debug('Job Not scheduled');
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.INFO,'Future Date Time only');
             ApexPages.addMessage(myMsg);
        }
    }
   global void execute(SchedulableContext SC) {
    AutomatedTestSetup_Controller.enqueueTests();   
   } 
 }