Monday, February 25, 2019

Executing classes from APEX Classes and APEX Test Execution....Analyzing the results....

Every few months, critical updates are released by Salesforce. As an architect, I needed to review and make sure that these updates won't have an adverse impact to our system.

If your system has a lot of custom code/development and lot of Installed Packages then you need to make sure that the system works correctly even after the updates are auto activated.


Go to APEX classes and hit the Run All test classes, this executes tests from Managed Packages as well.

The other option is to go to APEX test execution and selectively execute classes by specifying the namespace.

The critical thing after this steps is to be able to dissect the results generated as a result of the run.

Here are some queries to execute from WorkBench in BULK CSV mode.

SELECT AsyncApexJobId,Status,UserId FROM ApexTestRunResult
   SELECT ApexClassId,ApexLogId,ApexTestRunResultId,AsyncApexJobId,Id,Message,MethodName,Outcome,QueueItemId,RunTime,StackTrace,SystemModstamp,TestTimestamp FROM ApexTestResult where Outcome='Fail'
   SELECT ApexClassId,ApexLogId,ApexTestRunResultId,AsyncApexJobId,Id,Message,MethodName,Outcome,QueueItemId,RunTime,StackTrace,SystemModstamp,TestTimestamp FROM ApexTestResult where Outcome='Fail' and
   AsyncApexJobId='707S000000qe6mZIAQ'
   SELECT count(Id) FROM ApexTestResult where 
   AsyncApexJobId='707S000000qQmb7IAC' group by outcome
 
   SELECT count(Id) FROM ApexTestResult where 
   AsyncApexJobId=' ' group by outcome


When the tests are executed, an entry is created in APEX Test history indicating a TestRunID.
Drill down on the link and on the right you can see the Classes that have failed/passed.
Limitation is you can only view few at a time and can't see the details.

To get details, copy the RunID from the left and use it in the queries above, download the generated file from WorkBench and analyse the report.

I do multiple runs to make sure before/after update activation scenarios.

Tooling API

For most part I have used metadata API but never had the need to explore Tooling API aspect of Salesforce.  If you need to develop tools on metadata information from Salesforce this is the API to use.

We had a vendor move a lot of development to Production, the code coverage thru the Salesforce tools only indicated 22% code coverage while the vendor claimed to have 85% coverage.

I wondered if there was a way to crosscheck without to do a RunAll and that's where Tooling API came in handy.

Limitations: You can't use the queries in the normal sense from developer workbench; you have to go thru the RestExplorer approach.

However, you can use it in Developer console but then you can't export the data without having to do some hacks/

The Tooling API link is https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/intro_api_tooling.htm

Here are 2 situations where I needed to use:
a) Find code coverage when Salesforce and vendor claims were different
b) After a RunAll what is the code coverage for every single class in your system.

For a) run the following from WorkBench--utilities--RestExlorer

/services/data/v44.0/tooling/query/?q="SELECT+ApexClassOrTrigger.Name+NumLinesCovered+ NumLinesUncovered+FROM+ApexCodeCoverageAggregate"

Ther results will be in JSON format.
Take the response and paste in a JSON translator and you should be able to view and download the
revised output for a better understanding

OR

from developer console run the query, pasted a sample below.

SELECT ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverageAggregate 
WHERE ApexClassOrTrigger.Name = <Name>

SELECT PercentCovered 
FROM ApexOrgWideCoverage

SELECT NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverage 
WHERE ApexClassOrTriggerId = <ID>

SELECT ApexClassOrTriggerId, ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverageAggregate 
WHERE ApexClassOrTriggerId != NULL AND ApexClassOrTrigger.Name != NULL 
AND (NumLinesCovered &gt; 0 OR NumLinesUncovered &gt; 0) AND NumLinesCovered != NULL 
AND NumLinesUncovered != NULL ORDER BY ApexClassOrTrigger.Name

SELECT ApexClassOrTriggerId, ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverageAggregate 
ORDER BY ApexClassOrTrigger.Name