Print this page

How to get accurate code coverage from Metadata API

Knowledge Article Number 000219991
The "Run All Tests" within the UI may not retrieve the correct results in relation to the Organization Code Coverage. Please note that this value is always considered an estimation as the name suggests. For more information on this please review the following blog post by our Apex Product Manager Josh Kaplan on "How Code Coverage Works".

The Eclipse IDE can be used to run tests but this will only provide coverage on a class-by-class basis and does not provide an overall result for the Organization. Also you cannot copy these results from the IDE which limits us on how we can compute the Organization result from these in a spreadsheet.

The only way to get a valid result is from clearing the "ApexCodeCoverageAggregate" and "ApexCodeCoverage" tables prior to running all tests in the Org namespace or running a deployment. Running tests in the UI updates the mentioned tables but Metadata does not. This meaning that all deployments run tests on the "fly" but do not store the code coverage results in these tables. Also a deployment will only print the Organization coverage if it is below 75%, this KB will run through how to get the Organization coverage from a deployment regardless of success or failure deployments.
Resolution To get a valid Organization code coverage we need to use a recent deployment. It does not matter if it succeeded or failed.
**Please note, this will include the coverage of any additional Apex in the selected deployment and not just the Organization you are deploying too**

1) Get an “asyncId” of your latest deployment
i) To do this, go to the deployment status page and click on the latest deployment
ii) Once you have the deployment details open, if the name does not contain it, check the URL for the "asyncId" parameter and copy the Id out like so:
Getting AsyncId from Deployment Details

2) Download the metadata WSDL from your Organization under. You can get this from either:
i) Setup – Develop – API
ii) Or go to this URL - https:// {instance}
iii) and click on "Generate Metadata WSDL"

3) Once the page loads, right click, "Save as...", and save the file with extension set as ".wsdl"
i) It will set as "metadata.xml", change to "Save as type: All Files", and save as "metadata.wsdl"

4) Once you have the WSDL consume it in a tool like SoapUI

5) In SoapUI click: File –> New soapUI project –> click "Browse" and select the downloaded WSDL
i) Make sure “Create Requests” is checked

6) Next we must create a “checkDeployStatus” Metadata request as follows
i) Make sure you have the "asyncProcessId" set and "includeDetails" set to true
checkDeployStatus request

7) Save the response as an XML document
Save MD response

8) Open the newly saved XML file in Excel as follows
i) Open Excel (This scenario I am using Office 2007)
ii) ​​Click the Office button and select “Open”
iii) Select the file and press "Open"
iv) In the “Open XML” dialog, choose “Use the XML Source task pane”, and then hit OK on the next dialog
Excel open dialog

9) Next we need to get the right columns from the XML to load the appropriate values
i) Choose the “Id”, “Name”, “NumLocations”, “NumLocationsNotCovered” under the “runTestResult” node in the tree map. You can find out more on this columns in our RunTestResult  docs.
ii) Drag the selected 4 elements onto the empty sheet to the top left corner into cell A1
Excel mapping runTestResult tree node

10) Go to the “Data” tab in the Excel ribbon and click “Refresh All”
Refresh Data Excel tab

i) You should now see cells populated like the following. NOTE: The staggered results are not a problem here.
Data table

11)Go to the end of the C column (“ns2:numLocations”). Last row here is # 2342

12) In the cell just below it write the following formula to calculate the total lines to cover for all the classes
i) “=SUM(C2:C#)”  where # is the last cell in the sheet above the formula
ii) Do the same for column D where D is the number of lines not covered

13) Now we need one last cell to compute the Org total which is as follows
i) "= ((1-  (totalNumLocationsNotCovered / totalNumLocations) ) *100"
ii) In this scenario it is: “=(1- (D2342 / C2342))*100”
Final formulas

promote demote