演習 - コード カバレッジのテストを実行する

完了

単体テストに使用するツールと同様に、コード カバレッジで使用するツールは、プログラミング言語とアプリケーション フレームワークに応じて異なります。

Linux で実行する .NET アプリケーションをターゲットにする場合は、coverlet が一般的なオプションです。 coverlet は、.NET 用のクロス プラットフォームのコード カバレッジ ライブラリです。

.NET でのコード カバレッジの実行方法

コード カバレッジを収集する方法は、使用可能なコード カバレッジ ツールおよび使用するプログラミング言語とフレームワークによって異なります。

この Tailspin のシナリオでは、以下を確認します。

  • Windows 上の Visual Studio では、コード カバレッジを実行する方法が提供されます。

  • ただし、ここでは Linux でビルドを行うため、.NET 用のクロスプラットフォームのコード カバレッジ ライブラリである coverlet を使用できます。

    単体テスト プロジェクトには、coverlet.msbuild という NuGet パッケージが必要です。

  • コード カバレッジの結果は、別のツールで処理できるように、XML ファイルに書き込まれます。 Azure Pipelines では Cobertura および JaCoCo カバレッジ結果の形式がサポートされます。

    このモジュールでは、Cobertura を使用します。

  • Cobertura カバレッジの結果を人間が判読できる形式に変換するために、ReportGenerator というツールを使用できます。

  • ReportGenerator では、HTML を含む、多くの形式が提供されます。 HTML 形式では、.NET プロジェクトの各クラスの詳細なレポートが作成されます。

    具体的には、Azure Pipelines と一致する視覚的な外観を提供する、HtmlInline_AzurePipelines という HTML 形式があります。

.NET ツールを管理する方法

ReportGenerator などの .NET ツールは、コンソール アプリケーションを含む特殊な NuGet パッケージです。 .NET ツールは、グローバル ツールとして、またはローカル ツールとして管理できます。

グローバル ツールは一元的な場所にインストールされ、任意のディレクトリから呼び出すことができます。 1 つのバージョンのグローバル ツールが、マシン上のすべてのディレクトリに使用されます。

ローカル ツールは、特定のディレクトリにスコープが設定されている .NET ツールのより分離されたコピーです。 スコープを使用すると、異なるディレクトリに同じツールの別のバージョンを配置することができます。

特定のディレクトリのローカル ツールを管理するには、"マニフェスト ファイル" を使用します。 このファイルは JSON 形式であり、通常は dotnet-tools.json という名前です。 マニフェスト ファイルを使用すると、アプリケーションをビルドまたは実行するために必要な特定のツール バージョンを記述できます。

マニフェスト ファイルをソース管理とアプリケーションのソースに含めると、開発者とビルド システムは dotnet tool restore コマンドを実行して、マニフェスト ファイルにリストされているすべてのツールをインストールできます。 新しいバージョンのローカル ツールが必要な場合は、マニフェスト ファイルのバージョンを更新するだけです。

より分離された状態を維持するために、このモジュールではローカル ツールを使用します。 ReportGenerator ツールを含むツール マニフェストを作成します。 また、ビルド パイプラインを変更して、コード カバレッジの結果を人間が判読できる形式に変換する ReportGenerator ツールをインストールします。

コード カバレッジをローカルで実行する

パイプライン コードを記述する前に、プロセスを確認するために手動で試すことができます。

  1. Visual Studio Code で、統合ターミナルを開きます。

  2. 次の dotnet new コマンドを実行して、ローカル ツールのマニフェスト ファイルを作成します。

    dotnet new tool-manifest
    

    このコマンドにより、.config/dotnet-tools.json という名前のファイルが作成されます。

  3. 次の dotnet tool install コマンドを実行して、ReportGenerator をインストールします。

    dotnet tool install dotnet-reportgenerator-globaltool
    

    このコマンドでは、最新バージョンの ReportGenerator がインストールされ、ツール マニフェスト ファイルにエントリが追加されます。

  4. 次の dotnet add package コマンドを実行して、coverlet.msbuild パッケージを Tailspin.SpaceGame.Web.Tests プロジェクトに追加します。

    dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
    
  5. 次の dotnet test コマンドを実行して単体テストを行い、コード カバレッジを収集します。

    Note

    Visual Studio で PowerShell ターミナルを使用している場合、行連結文字はバックティック (`) であるため、複数行のコマンドではその文字を円記号 (\) の代わりに使用します。

    dotnet test --no-build \
      --configuration Release \
      /p:CollectCoverage=true \
      /p:CoverletOutputFormat=cobertura \
      /p:CoverletOutput=./TestResults/Coverage/
    

    コマンドが失敗する場合は、次のように実行してみてください。

    MSYS2_ARG_CONV_EXCL="*" dotnet test --no-build \
      --configuration Release \
      /p:CollectCoverage=true \
      /p:CoverletOutputFormat=cobertura \
      /p:CoverletOutput=./TestResults/Coverage/
    

    このコマンドは、以前に実行したものと似ています。 /p: フラグで、使用するコード カバレッジの形式と、結果を配置する場所を coverlet に示します。

  6. 次の dotnet tool run コマンドを実行し、ReportGenerator を使用して Cobertura ファイルを HTML に変換します。

    dotnet tool run reportgenerator \
      -- -reports:./Tailspin.SpaceGame.Web.Tests/TestResults/Coverage/coverage.cobertura.xml \
      -targetdir:./CodeCoverage \
      -reporttypes:HtmlInline_AzurePipelines
    

    プロジェクトのルートにある CodeCoverage フォルダーに多くの HTML ファイルが表示されます。

  7. Visual Studio Code で、CodeCoverage フォルダーを展開して、index.htm を右クリックし、[エクスプローラーで表示する] を選択します (macOS の場合は [Reveal in Finder]、Linux の場合は [Open Containing Folder])。

  8. エクスプローラー (macOS では Finder) で、index.htm をダブルクリックして Web ブラウザーで開きます。

    カバレッジ レポートの概要が示されます。

    A screenshot of the local code coverage report summary showing 7.7 percent line coverage.

  9. ページの一番下までスクロールし、クラスの種類ごとにカバレッジの詳細を確認します。

    A screenshot of local coverage report class summary showing coverage stats across classes found in the Tailspin.SpaceGame.Web code.

  10. TailSpin.SpaceGame.Web.LocalDocumentDBRepository<T> へのリンクを選択して、さらに詳細を表示します。

    GetItemsAsync メソッドは単体テストでカバーされていますが、CountItemsAsync メソッドにはカバレッジがないことがわかります。

    A screenshot of local class coverage detail with a visual representation of unit test coverage for two C# methods, one with all code lines green (covered) and one with all lines red (not covered).

    FetchOnlyRequestedGameRegion テスト メソッドでは GetItemsAsync メソッドが呼び出されますが、CountItemsAsync メソッドは呼び出されないため、これは当然のことです。 (テスト コードを確認するには、DocumentDBRepository_GetItemsAsyncShould.cs ファイルを参照してください。)

分岐を作成する

これでコード カバレッジ レポートをローカルでビルドできるようになったため、同じタスクを実行するビルド パイプラインにタスクを追加できる準備ができました。

このセクションでは、作業を保持するために、unit-tests ブランチに基づいて、code-coverage という名前のブランチを作成します。 実際には、通常、このブランチは main ブランチから作成します。

  1. Visual Studio Code で、統合ターミナルを開きます。

  2. ターミナルで、次の git checkout コマンドを実行して、code-coverage という名前のブランチを作成します。

    git checkout -B code-coverage
    

ビルド タスクを追加する

このセクションでは、コード カバレッジを測定するタスクをビルド パイプラインに追加します。

  1. Visual Studio Code で、azure-pipelines.yml を次のように変更します。

    trigger:
    - '*'
    
    pool:
      vmImage: 'ubuntu-20.04'
      demands:
      - npm
    
    variables:
      buildConfiguration: 'Release'
      wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot'
      dotnetSdkVersion: '6.x'
    
    steps:
    - task: UseDotNet@2
      displayName: 'Use .NET SDK $(dotnetSdkVersion)'
      inputs:
        version: '$(dotnetSdkVersion)'
    
    - task: Npm@1
      displayName: 'Run npm install'
      inputs:
        verbose: false
    
    - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)'
      displayName: 'Compile Sass assets'
    
    - task: gulp@1
      displayName: 'Run gulp tasks'
    
    - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt'
      displayName: 'Write build info'
      workingDirectory: $(wwwrootDir)
    
    - task: DotNetCoreCLI@2
      displayName: 'Restore project dependencies'
      inputs:
        command: 'restore'
        projects: '**/*.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Build the project - $(buildConfiguration)'
      inputs:
        command: 'build'
        arguments: '--no-restore --configuration $(buildConfiguration)'
        projects: '**/*.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Install .NET tools from local manifest'
      inputs:
        command: custom
        custom: tool
        arguments: 'restore'
    
    - task: DotNetCoreCLI@2
      displayName: 'Run unit tests - $(buildConfiguration)'
      inputs:
        command: 'test'
        arguments: '--no-build --configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Build.SourcesDirectory)/TestResults/Coverage/'
        publishTestResults: true
        projects: '**/*.Tests.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Create code coverage report'
      inputs:
        command: custom
        custom: tool
        arguments: 'run reportgenerator -reports:$(Build.SourcesDirectory)/**/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/CodeCoverage -reporttypes:HtmlInline_AzurePipelines'
    
    - task: PublishCodeCoverageResults@1
      displayName: 'Publish code coverage report'
      inputs:
        codeCoverageTool: 'cobertura'
        summaryFileLocation: '$(Build.SourcesDirectory)/**/coverage.cobertura.xml'
    
    - task: DotNetCoreCLI@2
      displayName: 'Publish the project - $(buildConfiguration)'
      inputs:
        command: 'publish'
        projects: '**/*.csproj'
        publishWebProjects: false
        arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)'
        zipAfterPublish: true
    
    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifact: drop'
      condition: succeeded()
    

    このバージョンは既存の構成に基づきます。 追加した部分の概要を次に示します。

    Azure Pipelines タスク Display name 説明
    DotNetCoreCLI@2 .NET ツールをローカル マニフェストからインストールする マニフェスト ファイル (dotnet-tools.json) にリストされているツールをインストールします
    DotNetCoreCLI@2 Run unit tests - $(buildConfiguration) 単体テストを実行し、Cobertura 形式でのコード カバレッジの収集も行います
    DotNetCoreCLI@2 Create code coverage report Cobertura の出力を HTML に変換します
    PublishCodeCoverageResults@1 Publish code coverage report パイプラインにレポートを発行します

変更をコミットしてブランチを GitHub にプッシュする

ここでは、変更を GitHub にプッシュし、パイプラインの実行を確認します。 現在、code-coverage ブランチにいることを思い出してください。

必須ではありませんが、ここで各ファイルを個別に追加してコミットし、それぞれの変更がわかりやすいコミット メッセージに関連付けられるようにします。

  1. Visual Studio Code で、ターミナルに移動します。

  2. coverlet.msbuild パッケージへの参照が含まれるようになった、Tailspin.SpaceGame.Web.Tests.csproj ファイルを追加してコミットします。

    git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj
    git commit -m "Add coverlet.msbuild package"
    
  3. ツール マニフェスト ファイル (dotnet-tools.json) を追加してコミットします。

    git add .config/dotnet-tools.json
    git commit -m "Add code coverage"
    
  4. 更新されたビルド構成を含む azure-pipelines.yml を追加してコミットします。

    git add azure-pipelines.yml
    git commit -m "Add code coverage"
    
  5. code-coverage ブランチを GitHub にプッシュします。

    git push origin code-coverage
    

Azure Pipelines でのテストの実行を監視する

ここで、パイプラインでのテストの実行を確認してから、Azure Test Plans からの結果を視覚化します。

  1. Azure Pipelines で、手順ごとにビルドをトレースします。

  2. ビルドが完了したら、概要ページに戻り、[コード カバレッジ] タブを選びます。

    ローカルでテストを実行したときと同じ結果が表示されます。

    A screenshot of Azure Pipelines showing the Code Coverage tab, with code coverage report summary showing 7.7 percent line coverage.

    オプションの手順として、Azure Pipelines からの結果を調べることができます。

ダッシュボード ウィジェットを追加する

前のセクションでは、[テスト結果の傾向] ウィジェットをダッシュボードに追加しました。これを使って、他のユーザーがテスト結果の傾向を時間の経過に従ってすばやく確認できます。

ここでは、コード カバレッジの概要を示す 2 番目のウィジェットを追加します。

  1. 新しいブラウザー タブで、marketplace.visualstudio.com に移動します。

  2. [Azure DevOps] タブで、「code coverage」を検索します。

  3. [Code Coverage Widgets] を選択します (Shane Davis によって公開されています)。

  4. [Get it free](無料で入手) を選択します。

  5. ドロップダウン リストで、対象の Azure DevOps 組織を選択します。

  6. [インストール] を選択します。

  7. Azure DevOps に戻ります。

  8. [Overview]>[Dashboards] に移動します。

  9. [編集] を選択します。

  10. Code Coverage」を検索し、[Code Coverage] を選択します。

    A screenshot of Visual Studio Marketplace showing the Code Coverage widget card.

  11. コード カバレッジをキャンバスにドラッグします。

  12. 歯車アイコンを選択してウィジェットを構成します。

  13. 次の設定を除き、すべての設定を既定のままにします。

    • 幅:「2」と入力します
    • ビルド定義:パイプラインを選択します
    • Coverage measurement (カバレッジの測定): [行数] を選択します
  14. [保存] を選択します。

  15. [編集完了] を選択します。

    ウィジェットには、単体テストでカバーされるコードの割合が表示されます。

    A screenshot of Azure DevOps Code Coverage widget showing 8 percent coverage of the sample project.

これで、パイプラインにコード カバレッジが設定されました。 既存のコード カバレッジは低くなっていますが、時間の経過と共に改善できるベースラインがあります。

後から、テストでカバレッジの最小しきい値が提供されるかどうかを確認するように、coverlet を構成できます。 しきい値は、要件に応じて 30%、50%、または 80% のカバレッジにすることができます。 テストでこれより少ない量がカバーされている場合、ビルドは失敗します。

コード カバレッジ ファイルを削除する

先ほど Reportgenerator を実行したときに、プロジェクトのルートにある CodeCoverage フォルダーに多くの HTML ファイルが表示されていたことを思い出してください。

これらの HTML ファイルは、ソース管理に含めることは意図されておらず、必要なくなりました。 プロジェクトの .gitignore ファイルは、CodeCoverage ディレクトリの内容を無視するように既に設定されていますが、今後のモジュールで Git リポジトリに追加されないように、これらのファイルを削除することをお勧めします。

Visual Studio Code で、ターミナル ウィンドウに移動し、プロジェクトのルート ディレクトリでこのコマンドを実行します。

rm -rf CodeCoverage/