モヤるポイント
Azure Pipelines を使って .NET Core のアプリケーションの単体テストを実行するとき、以下のような YAML を書いて単体テストを実行していたと思います。
- task: DotNetCoreCLI@2 inputs: command: 'test' projects: '$(Build.SourcesDirectory)\**\Test.*.csproj' arguments: --collect "Code coverage"
こんなタスクを組み込んであげると、 Azure Pipelines の実行結果画面で、単体テストの実行結果を参照できます。
[Tests] タブを開くと、以下のような形でテストの実行結果をさらに詳しく参照することもできます。
しかし、 [Code Coverage] タブを開くと、そこにはコードカバレッジの情報は表示されません。 何やらファイルダウンロードを行うためのリンクが表示されます。 このファイルをダウンロードして、ローカルの Visual Studio Enterprise で開くと、コードカバレッジの情報が参照できるのですが。。。 Visual Studio Enterprise を持っていないとこのファイルを開けなかったり、オペレーションがめちゃくちゃ煩雑だったり、とまったくうれしくない使用感です。
やりたいこと
今回は前述した [Code Coverage] タブを開いたら、そこにコードカバレッジの詳細情報を表示できるようにしていきたいと思います。 なお今回使用するサンプルは、以下の GitHub リポジトリに公開してありますので、ご自由に参照してください。
Azure DevOps のセットアップ
まずは Azure DevOps のマーケットプレースに行って、以下の拡張機能をインストールしましょう。
YAML の作成
続いてビルドパイプラインを作成します。
各種設定
まずは設定部分です。
trigger: none variables: System.Debug: True BuildConfiguration: 'Debug' TargetSolution: '$(Build.SourcesDirectory)\TestCoverageReportSample_Core\TestCoverageReportSample.sln' TestProjects: '$(Build.SourcesDirectory)\TestCoverageReportSample_Core\test\**\Test.*.csproj' pool: vmImage: 'windows-latest'
今回は手動でビルドパイプラインを実行するだけなので、トリガーは none に設定しておきます。 またビルドマシンも最新版の MS-Hosted な Windows マシンを使用します。
変数はビルドの Configuration とソリューションのパス、テストプロジェクトのパスを設定しています。 Configuration は今回 Debug を使用していますが、特に理由はありません。 このリポジトリは複数ソリューションが含まれるリポジトリですので、ソリューションやテストプロジェクトのパスはそれ反映した形で定義しています。
System.Debug
変数は、ビルドパイプライン内の各タスクの出力するデバッグログを出力するための設定です。
デバッグログが不要なら、この設定は必要ありません。
アプリケーションのビルド
- task: DotNetCoreCLI@2 displayName: 'NuGet パッケージの復元' inputs: command: 'restore' projects: '$(TargetSolution)' feedsToUse: 'select' - task: DotNetCoreCLI@2 displayName: 'アプリケーションのビルド' inputs: command: 'build' projects: '$(TargetSolution)' arguments: '--configuration $(BuildConfiguration)'
今回のアプリケーションは .NET Standard 2.0 準拠のクラスライブラリプロジェクトと、そのライブラリの単体テストプロジェクト(.NET Core 3.1)で構成してあります。 なので VSBuild ではなく、 dotnet CLI を用いて実行しています。 最初のタスクで NuGet パッケージの復元を行い、続いてソリューション全体のビルドを実行しています。
アプリケーションのテスト
- task: DotNetCoreCLI@2 displayName: '単体テストの実行' inputs: command: 'test' projects: '$(TestProjects)' arguments: '--configuration $(BuildConfiguration) --collect "XPlat Code coverage" -- RunConfiguration.DisableAppDomain=true'
アプリケーションのテストも dotnet CLI を用いています。
この時ポイントとなるのが --collect "XPlat Code coverage"
の部分です。
これはコードカバレッジを Coverlet で実行するための設定です。
Visual Studio 2019 で .NET Core 3.1 の [MSTest テスト プロジェクト(.NET Core)] を作成すると、既定で以下の NuGet パッケージが含まれてきます。
この --collect "XPlat Code coverage"
の設定を行うことで、 Coverlet を用いてコードカバレッジの計測が行われるようになります。
計測結果は [coverage.cobertura.xml] という名前の XML ファイルとして出力されます。
出力場所は $(Agent.TempDirectory)
のディレクトリ配下にランダム名前のディレクトリが置かれ、その中に配置されます。
出力されるファイルのパスは、 System.Debug
変数を true
に設定しておくことで参照できます。
単体テストで使用できるオプションについては、以下を参照してください。
コードカバレッジレポートの作成と発行
- task: reportgenerator@4 displayName: 'コードカバレッジレポートの作成' inputs: reports: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' targetdir: '$(System.DefaultWorkingDirectory)\TestResults\Coverage\Reports' reporttypes: 'Cobertura' - task: PublishCodeCoverageResults@1 displayName: 'コードカバレッジレポートの発行' inputs: codeCoverageTool: 'Cobertura' summaryFileLocation: '$(System.DefaultWorkingDirectory)\TestResults\Coverage\Reports\Cobertura.xml'
最後に、マーケットプレースからインストールした Report Generator を使って、コードカバレッジレポートの作成を行います。
アプリケーションのテストを行うタスクで出力した [coverage.cobertura.xml] を入力として、 [Cobertura] 形式のカバレッジレポートを作成します。
コードカバレッジのレポート作成を [Cobertura] 形式で実行すると、 targetdir
に設定したディレクトリに、 [Cobertura.xml] が出力されます。
このファイルを PublishCodeCoverageResults のタスクを用いて発行します。
実行結果
ビルドパイプラインを実行すると、以下のようなビルド結果が [Summary] タブに表示されます。
ビルド結果(Summary)の画面は、今までとほとんど変わりありません。 ただし、 Build Artifacts として、カバレッジレポートの情報がアップロードされている点と、コードカバレッジ率に少々変化があります*1。
Build Artifacts の方には、アップロードしたコードカバレッジの情報と、そこから生成した HTML のレポートが含まれています。
次に [Code Coverage] のタブを開いてみます。
ここには、先ほど Build Artifacts としてアップロードされたコードカバレッジの詳細情報が表示されます。 また表示されているクラスのリンクを押下すると、さらに詳細なカバレッジレポートを参照できます。
まとめ
今回は Azure Pipelines のビルド結果画面で、単体テストのコードカバレッジを表示する方法について解説しました。 Visual Studio Enterprise を持っていない場合でも、この方法ならコードカバレッジのデータを参照することができますので、活用してみてください。