便利機能のご紹介。開発者コンソールの匿名実行Apexツールでテストカバー率一覧を取得してみる
こんにちは!
開発者コンソールの匿名実行Apexツールは活用してますか? そもそも、開発者コンソールの匿名実行Apexツールとはなんだ!?って方、 下記ヘルプを参照してください。m(_ _)m https://help.salesforce.com/apex/HTViewHelpDoc?id=code_dev_console_execute_anonymous.htm&language=ja 本題ですが、 このツールを使っていろいろとやってみようと思います。 その第1弾として、クラスとトリガのテストカバー率を取得するApexコードを書いてみました! ※テストクラスの実行はしません。現在のカバー率を取得します。 まず、なぜこのコードを書いたかというと、ご存知の方もいらっしゃると思いますが、 Winter’14のリリースでApexクラス一覧からクラスのカバー率の列が削除されましたよね。
https://resources.docs.salesforce.com/186/latest/ja-jp/sfdc/pdf/salesforce_winter14_release_notes.pdf ↑306ページ なんで削除されたんだ?と思った方も多いのではないでしょうか。(たぶん…) ということで、どうにか一覧表として取得できないかなぁと思い、書いてみました。 開発者コンソールの[Debug]->[Open Execute Anonymous Window]で匿名実行Apexツールを開き、 下記コードを貼り付けて[Execute]ボタンをクリックすると、 ドキュメントの「私の個人ドキュメント」フォルダにクラスとトリガのカバー率一覧のファイルが XMLスプレッドシート形式で保存されます!!
// ClassとTriggerのカバー率を取得するクエリ
String queryStr = 'Select+id,ApexClassorTriggerId,ApexClassorTrigger.Name,NumLinesCovered,NumLinesUncovered+from+ApexCodeCoverageAggregate+order+by+ApexClassorTrigger.Name';
HttpRequest req = new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v37.0/tooling/query/?q='+queryStr);
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);
Map<String, Object> objMap = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
List<Object> objList = (List<Object>)objMap.get('records');
// クラス一覧ワークシート
String clsListWS = '';
// トリガ一覧ワークシート
String trgListWS = '';
clsListWS += '<Worksheet ss_Name="クラス一覧">rn' +
'<Table ss_ExpandedColumnCount="7" x_FullColumns="1" x_FullRows="1" ss_DefaultColumnWidth="54" ss_DefaultRowHeight="13.5">rn' +
'<Column ss_AutoFitWidth="0" ss_Width="21.75"/>rn' +
'<Row>rn' +
'<Cell><Data ss_Type="String">クラス一覧</Data></Cell>rn' +
'</Row>rn' +
'<Row>rn' +
'<Cell><Data ss_Type="String">No</Data></Cell>rn' +
'<Cell><Data ss_Type="String">Id</Data></Cell>rn' +
'<Cell><Data ss_Type="String">Name</Data></Cell>rn' +
'<Cell><Data ss_Type="String">NumLinesCovered</Data></Cell>rn' +
'<Cell><Data ss_Type="String">NumLinesUncovered</Data></Cell>rn' +
'<Cell><Data ss_Type="String">TotalNumLines</Data></Cell>rn' +
'<Cell><Data ss_Type="String">Coverage</Data></Cell>rn' +
'</Row>rn';
trgListWS += '<Worksheet ss_Name="トリガ一覧">rn' +
'<Table ss_ExpandedColumnCount="7" x_FullColumns="1" x_FullRows="1" ss_DefaultColumnWidth="54" ss_DefaultRowHeight="13.5">rn' +
'<Column ss_AutoFitWidth="0" ss_Width="21.75"/>rn' +
'<Row>rn' +
'<Cell><Data ss_Type="String">トリガ一覧</Data></Cell>rn' +
'</Row>rn' +
'<Row>rn' +
'<Cell><Data ss_Type="String">No</Data></Cell>rn' +
'<Cell><Data ss_Type="String">Id</Data></Cell>rn' +
'<Cell><Data ss_Type="String">Name</Data></Cell>rn' +
'<Cell><Data ss_Type="String">NumLinesCovered</Data></Cell>rn' +
'<Cell><Data ss_Type="String">NumLinesUncovered</Data></Cell>rn' +
'<Cell><Data ss_Type="String">TotalNumLines</Data></Cell>rn' +
'<Cell><Data ss_Type="String">Coverage</Data></Cell>rn' +
'</Row>rn';
Integer clsCnt = 1;
Integer trgCnt = 1;
for(Object obj : objList){
Map<String, Object> codeCoverageObj = (Map<String, Object>)obj;
Map<String, Object> clsOrTrgObj = (Map<String, Object>)codeCoverageObj.get('ApexClassOrTrigger');
Double numLinesCovered = Double.valueOf(codeCoverageObj.get('NumLinesCovered'));
Double totalNumLines = Double.valueOf(codeCoverageObj.get('NumLinesCovered')) + Double.valueOf(codeCoverageObj.get('NumLinesUncovered'));
// クラス単体のカバー率を計算
Decimal coverage = 0;
if(numLinesCovered != 0){
coverage = (numLinesCovered / totalNumLines) * 100;
coverage = coverage.setScale(0, System.RoundingMode.HALF_UP);
}
String clsOrTrgId = String.valueOf(codeCoverageObj.get('ApexClassOrTriggerId'));
// ClassのIdのPrefix
if(clsOrTrgId.startsWith('01p')){
clsListWS += '<Row>rn' +
'<Cell><Data ss_Type="Number">' + clsCnt + '</Data></Cell>rn' +
'<Cell><Data ss_Type="String">' + clsOrTrgId + '</Data></Cell>rn' +
'<Cell><Data ss_Type="String">' + String.valueOf(clsOrTrgObj.get('Name')) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="Number">' + String.valueOf(numLinesCovered) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="Number">' + String.valueOf(codeCoverageObj.get('NumLinesUncovered')) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="Number">' + String.valueOf(totalNumLines) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="String">' + coverage + '%' + '</Data></Cell>rn' +
'</Row>rn';
clsCnt++;
}
// TriggerのIdのPrefix
else if(clsOrTrgId.startsWith('01q')){
trgListWS += '<Row>rn' +
'<Cell><Data ss_Type="Number">' + trgCnt + '</Data></Cell>rn' +
'<Cell><Data ss_Type="String">' + clsOrTrgId + '</Data></Cell>rn' +
'<Cell><Data ss_Type="String">' + String.valueOf(clsOrTrgObj.get('Name')) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="Number">' + String.valueOf(numLinesCovered) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="Number">' + String.valueOf(codeCoverageObj.get('NumLinesUncovered')) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="Number">' + String.valueOf(totalNumLines) + '</Data></Cell>rn' +
'<Cell><Data ss_Type="String">' + coverage + '%' + '</Data></Cell>rn' +
'</Row>rn';
trgCnt++;
}
}
clsListWS += '</Table>rn' +
'</Worksheet>rn';
trgListWS += '</Table>rn' +
'</Worksheet>rn';
String workBook = '<?xml version="1.0"?>rn' +
'<?mso-application progid="Excel.Sheet"?>rn' +
'<Workbook >rn' +
clsListWS +
trgListWS +
'</Workbook>';
Document doc = new Document();
String timeStamp = DateTime.now().format('yyyyMMddHHmmss');
doc.Name = 'TestCoverage_' + timeStamp + '.xml';
doc.DeveloperName = 'TestCoverage_' + timeStamp + '_xml';
doc.FolderId = UserInfo.getUserId();
doc.Body = Blob.valueOf(workBook);
doc.type = 'xml';
insert doc;
※このコードを実行前に「リモートサイトの設定」が必要となります。 [設定]->[セキュリティのコントロール]->[リモートサイトの設定]で下記URLを設定しておいてください。 https://【ログイン環境のインスタンス】.salesforce.com 出力されるファイルはこんな感じです↓
ぜひ活用してみてください!