はじめに
今回はC#でプロジェクトを構築している前提でPRを出した際にコードカバレッジの増減を表示してくれるCIの作り方を紹介したいと思います。
具体的にはcoverlet.collector
とoctcov
というOSSを利用して実現していきます。
coverlet.collectorを用いたテスト実行 + コードカバレッジ取得
概要
coverlet.collector
とは.NET用のコードカバレッジフレームワークです。これを用いることでdotnet test
を実行した際に、一緒にコードカバレッジを取得することができます。
Coverlet is a cross platform code coverage framework for .NET, with support for line, branch and method coverage. It works with .NET Framework on Windows and .NET Core on all supported platforms.
// DeepL翻訳
Coverletは.NET用のクロスプラットフォームのコードカバレッジフレームワークで、行、ブランチ、メソッドのカバレッジをサポートしています。
また出力フォーマットには以下に対応しています。
cobertura
json
lcov
opencover
teamcity
プロジェクトに導入する
XUnit
もNUnit
にも対応しています。テストプロジェクトに対してNuGet経由でインストールを行なってください。
$ dotnet add package coverlet.collector
コマンド利用方法
dotnet test
を実行する際に、--collect:"XPlat Code Coverage"
を追加してあげます。
# 必須 : --collect:"XPlat Code Coverage" # 任意 : Formatにより出力フォーマットを設定できる。cobertura、json、lcov、opencover、teamcityに対応 # 任意: --results-directoryにより出力先フォルダを指定できる。出力先ディレクトリ/<GUID>/coverage.cobertura.xmlのように出力され、GUIDは必ずついてくる $ dotnet test --collect:"XPlat Code Coverage;Format=cobertura,lcov;" --results-directory:"./Result" Determining projects to restore... 復元対象のすべてのプロジェクトは最新です。 ... 成功! -失敗: 0、合格: 1、スキップ: 0、合計: 1、期間: 6 ms - TestProject.dll (net8.0) 添付ファイル: <ProjectRoot>/Result/4d630dc9-7e14-4956-b55c-d4acce16eeae/coverage.cobertura.xml <ProjectRoot>/Result/4d630dc9-7e14-4956-b55c-d4acce16eeae/coverage.info
またコメントでも書きましたが、出力されるファイルは必ずGUID
名のディレクトに中に格納されます。どうやらこのディレクトリをなくすことはできないようです。
取得範囲を絞る
--colect
にオプションを増やすことで、カバレッジを取得するパスやアセンブリを指定することができます。
Exclude
やInclude
、IncludeDirectory
、IncludeTestAssembly
、ExcludeByAttribute
などなど多様なオプションがあるので公式ドキュメントを参照してみてください。
coverlet/Documentation/VSTestIntegration.md at master · coverlet-coverage/coverlet · GitHub
octcovを用いてプルリクの際にコードカバレッジ差分を表示する
概要
octocov
はコードメトリクスを収集するためのツールキットです。CLIとしても利用できますし、CIでも利用できます。
octocov is a toolkit for collecting code metrics (code coverage, code to test ratio, test execution time and your own custom metrics).
// DeepL翻訳
octocovは、コード・メトリクス(コード・カバレッジ、コード対テスト比、テスト実行時間、独自のカスタム・メトリクス)を収集するためのツールキットです。
またカバレッジレポートのフォーマットは沢山あるのですが、octcov
は以下に対応しています。
Go coverage
LCOV
SimpleCov
Clover
Cobertura
JaCoCo
coverlet.collector
・octcov
は両方ともLCOV
に対応しているので、今回はそれを利用していきます。
設定ファイルの作成
octocov
には設定ファイルを利用することで様々な設定ができます。場所はどこでも良いのですが.octocov.yml
ファイルを作成して中身を記述してください。
詳細はreadmeを見てみて欲しいのですが、私がよく利用する設定を載せておきます。
github.com
# .octocov.yml # コードカバレッジが60%以上でないとexit 1を返す # coverage/*/coverage.infoを読み込む(coverlet.collectorでLCOVの出力先をここに設定する) coverage: acceptable: 60% paths: - coverage/*/coverage.info # テストの実行時間として利用するsteps (Actions側でnameを'dotnet test'にしている場合) testExecutionTime: steps: - 'dotnet test' # codeとtestの割合を計算するのに利用するファイル codeToTestRatio: code: - 'ClassLibrary1/**/*.cs' test: - 'TestProject/**/*.cs' # プルリクエストにコメントをつける comment: if: is_pull_request hideFooterLink: true # JobのSummaryを表示する summary: if: true # 差分を表示するためにArtifactを利用 report: if: is_default_branch datastores: - artifact://${GITHUB_REPOSITORY}/dotnet-test-report diff: datastores: - artifact://${GITHUB_REPOSITORY}/dotnet-test-report
actionsを作成する
最後にcoverlet.collector
+ octcov
を利用するActionsを書きます。
name: test on: push: branches: main pull_request: branches: main jobs: test: runs-on: ubuntu-latest permissions: contents: read pull-requests: write actions: read env: LCOV_DIR: ${{ github.workspace }}/coverage steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v3 with: dotnet-version: 8.0.x - run: dotnet restore - run: dotnet build --configuration Release --no-restore - name: dotnet test run: dotnet test --configuration Release --no-restore --no-build --verbosity normal --collect:"XPlat Code Coverage;Format=lcov;" --results-directory:${{ env.LCOV_DIR }} - uses: k1LoW/octocov-action@v1 with: config: .octocov.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPOSITORY: ${{ github.repository }}
結果
プルリクエストを出すとコードカバレッジの増減を表示してくれ、デフォルトブランチにマージするとArtifact
に結果を保存してくれます。
また以下の3つを設定している + デフォルトブランチとの差分表示をするように設定しています。
Code Coverage
: コードカバレッジCode to Test Ratio
: コードとテストコードの比率Test Execution Time
: テスト実行時間
また設定したcoverage: acceptable 60%
以下の場合はfailになります。
考察
PR単位でコードカバレッジ増減を表示することで、PR作成 => カバレッジ低下 => テストコード作成
の流れができて、良い運用ができるのではないかなと思います。
定期的にカバレッジを取得するのも良いかとは思うのですが、実装した際に一緒にテストコードを実装するのが個人的には理想かなと。
さいごに
またUnityで公式パッケージであるCode Coverageを利用すると同様のことができるので、それも後でブログにて紹介しようと思います。