どんな仕事でも単体テストに関しては大体やること同じなので自分用のリンク集&メモです。参考サイトさんたちに感謝いたします。
使うツール類
- Visual Studio 2022
- Fine Code Coverage
- MSTest
- Coverlet
- ReportGenerator
単体テスト基礎
MSTest
考え方
基本的にはMicrosoftのBest Practiceに沿えばよいが、その他いくつか。
ホワイトテストのための直行表作成
Inputパラメータのパターンが多い場合は直行表を作る。レビュワーは直行表ベースでレビューを行う。
カバレッジ
闇雲にコードカバレッジが高いから品質が良いというわけでもない。テストする工数と品質のメリデメを勘案してテストする箇所を決める。
Microsoftは目安を出していないが、自作部分(特にビジネスロジック)は適宜DI、モックして本来カバー率100%を目指すべきと考える(色々意見はあるけど)。ただし、テンプレートから作成された部分やリポジトリとか外部ライブラリを呼び出しているだけのものは例外的にカバー率低でも許容する。
個人的に思うのは、テストケース数が多いから、「必要最低限」のテスト数に絞るという記事を見かけることがある(ペアワイズ法とか)が、インプットパターン数が多いことを単体テストをしないことの言い訳にしてはならない。そういう場合は可能な限りリファクタリングするか、直行表を作ったうえでDataRowやヘルパーメソッドとかでテンプレート化し、なるべく単体テストケースをシンプルに量産することを推奨。
単体テストが条件網羅とか詳細を確認するのに適しているので、手動でパターンテストをするとなるともっと大変。
目指すべきカバレッジのパターンは直行表を作っていれば自然とC2になるはず。
適宜コードメトリックスを取得し問題があればリファクタ
複雑なコードはテストも複雑になる。
命名規則
- フォルダ構造:テストプロジェクトもテスト対象プロジェクトとフォルダ構造は同じにする
- プロジェクト名:テスト対象プロジェクト名.Tests.csproj
例:MyBankProject.csproj → MyBankProject.Tests.csproj
- クラス名:テスト対象クラス名+Tests.cs
例:MyBankClass.cs → MyBankClassTests.cs
- メソッド名:テスト対象クラス名_テスト対象メソッド名_When_条件_Then_想定
例:MyBankClassのCalculateAmountメソッド → MyBankClassTests_CalculateAmount_When_Amount_Not_Zero_Then_Returns_Correct_Amount
その他
- モックツールについて
モックには、Moqを使いたいところだが、NSubstituteを使う方が当面は安全か。
ASP.Netアプリのテスト
- ModelのテストはValidatorを利用する
- Filterのテスト
カバレッジを取得する
Enterprse Editionを使っている場合。
Enterprise Editionではない場合、CoverletとReport Generatorを使う。
上記のCoverletとReport Generatorのレポートをpowershellで出力する。
追記:Visual Studio上で見るなら以下のツールが使えると教えていただきました!
Git hookでCommit前 (or Push前)に単体テストを実行
チーム開発をする場合はGit hookスクリプトをチェックインして、それを各開発環境のgit hookディレクトリに配置してもらう。
DevOpsでテスト結果、カバレッジを発行する
# ASP.NET Core (.NET Framework)
# Build and test ASP.NET Core projects targeting the full .NET Framework.
# Add steps that publish symbols, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core
trigger:
- develop
pool:
vmImage: 'windows-latest'
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
steps:
- task: NuGetToolInstaller@1
- task: NuGetCommand@2
inputs:
restoreSolution: '$(solution)'
- task: VSBuild@1
inputs:
solution: '$(solution)'
msbuildArgs: '/p:SkipInvalidConfigurations=true'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: DotNetCoreCLI@2
inputs:
command: 'test'
projects: '**/*.Tests.csproj'
arguments: '--configuration $(buildConfiguration) --collect:"XPlat Code Coverage"'
publishTestResults: true
- task: PublishCodeCoverageResults@1
displayName: 'Publish code coverage'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: $(Agent.TempDirectory)/*/coverage.cobertura.xml
※PublishCodeCoverageResults@1はバージョン@2を使うこと推奨。(調べてないだけです。。。いつか更新したい。)
DevOpsのBuild ValidationでPull Request時にトリガーしテスト失敗したらマージさせない
BuildValidationについて注意点
ちなみに、BuildValidationが正常に実行されるには、pipelineのymlファイルがソースとターゲットブランチで両方に存在する必要がある。
FeatureブランチからdevelopブランチにPRによりマージしたとき、①と②がそろっているとき以下のように2回Pipelineが実行されるらしい。(Copilotに質問しただけでちゃんと動作確認したわけではないので、いつか確認予定。)
①developブランチにTrigger: developに設定したPipelineがある
②developブランチにBuildValidationが設定されている
- 1回目:BuildValidationにより、マージ元ブランチ(Featureブランチ)を自動検知し、それに対してPipeline実行(ここで失敗した場合は2回目は実行されない)
- 2回目:Triggerにより、developブランチの更新を検知し、マージ先ブランチに対してPipeline実行