Salesforce ApexCodeCoverageを活用したCIの品質向上
はじめに
Trailblazerの皆様こんにちは、Ubiregiでコーポレートエンジニアとして活動している川名と申します。
今回は、以前書いた記事「Salesforce CLIとGitHub Actionsを活用したCI/CDパイプラインの高速化」の改善版について共有出来ればと思います。
この記事で分かること
Salesforce開発におけるリリース検証の効率化と品質向上の手法
sfコマンドとToolingAPIの組み合わせ方法
テストクラスの都度指定による課題
前回投稿した内容では、pull request単位でテストを指定する事により、CI速度を向上させる事が出来ましたが、運用する中で「デプロイしたいApexクラスが複数のテストクラスに依存している」というケースでの煩雑さが課題になりました。
テストクラスの作成ポリシー等によってはこういう問題は発生しにくいと思いますが、複数のテストクラスによって75%のカバー率を達成している場合、検証に失敗してしまうためそもそもデプロイ出来ません。
※Salesforceでは75%以上のテストカバー率が必要というPlatformのルールがあります。
仮にカバー率がクリア出来ていたとしても、関連のテストクラスが存在するのにスルーしてデプロイするのは品質的によろしくありません。
しっかりとテストする必要はあるのですが、ある程度のクラス数になってくると、修正したクラスがどのテストクラスによって品質保証されているか判断するのは容易じゃないです。
※余談ですが、Salesforceを活用している組織の7割くらいはApexクラスが存在しているという話をSWTT 2023 Autumun(11/28~29)で聞いて、まだまだApexの出番はなくならなそうだなと感じました。(ノーコードとの棲み分け設計や組織でのポリシーがより重要になりそうですね)
テストクラス群を一発で取得する方法
そんな背景のもと解決策を探していたところ、ToolingAPIに「ApexCodeCoverage」というオブジェクトがある事を知りました。
このオブジェクトは対象クラスとそれをカバーしているテストクラスが行レベル取得出来ます!(きっと開発者コンソールで確認できるカバレッジもこの情報を元にしているんですね)
参考:https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_apexcodecoverage.htm
Ubiregiでは毎日定期的に本番組織上でテストを実行しているため、常に最新の情報が格納されている様で、こちらを利用することにしました。
以下にコマンドサンプルを載せておきます。
ApexTestClassというのがテストクラス名になるので、その情報をjsonで取得してユニークにしてあげれば対応表が作れます。
ApexClassOrTriggerにはデプロイしたいクラス名をカンマ区切りなどで入れてあげます。
この辺りはCI側でテキスト加工して頑張っています。
sf data query --query " SELECT ApexTestClassId, ApexTestClass.Name \
FROM ApexCodeCoverage \
WHERE ApexClassOrTrigger.Name in ('SampleClass') " \
--use-tooling-api \
--json | jq -r '[.result.records[].ApexTestClass.Name] | unique'
CIでの使い方
テストクラス名が分かれば、あとはdeployコマンドの--testsオプションに渡すだけです。
この時に注意する点としては、pull request内で新たに作成したテストクラスはこの時点ではApexCodeCoverageに含まれていないため、別途deployコマンドの--testsに追加する必要があります。
ここはCI側で新規テストと既存テストを両方見た上でuniqueになるように工夫しています。
sf project deploy start -x ./package/package.xml \
-l RunSpecifiedTests --tests Test1 Test2 AddedTest \
--dry-run \
--json
まとめ
この方法によって検証の度に関連するテストクラスを手動で確認する必要がなくなり、大幅な工数削減と品質担保が実現出来たと思います。
ToolingAPIには多くのオブジェクトが存在しているので、まだまだ活用しきれていないなーという印象です。
最近気になっているのは、MetadataComponentDependency (Beta)というオブジェクトです。
これはカスタム項目などの画面で表示できる「使用場所」の情報が自動化できるため、色々な活用方法がありそうですね。
まだ制限がけっこうあったりするのですが、sh側などで頑張ればいい感じに出来そうです。
また活用の機会があればご紹介したいと思います。
それでは楽しいSalesforce Lifeを!
余談
先日、SWTT 2023 Autumnに現地参戦してきました。
スタンプラリーがあったのですが、その中で印象的だったのは荒川の河川敷のマイクロプラスチックの除去活動。
靴底からも知らない間に排出されている様で、こういう活動を通して少しでも自分が出したゴミをリセットする事が大切なんだな、と改めて感じました。
他にも知らない機能があったりと大変勉強になった2日間でした。また日々の業務に活かせればと思います。