2024-06-24|閱讀時間 ‧ 約 27 分鐘

.NET Code Coverage

Code Coverage 是什麼?

程式碼覆蓋率(Code Coverage)是一種軟體測試指標,用百分比表示,數值越高越好。

  1. 100% 的意思是「整個程式碼在測試中都被執行到」。
  2. 80% 的意思是「有80%的程式碼在測試中被執行到,還有20%的程式碼沒有被測試覆蓋」。
  3. 20% 的意思是「只有20%的程式碼在測試中被執行到,有80%的程式碼沒有經過測試」。

常見 Unit Test 在 80% 認定為達到基本標準;90% 算是良好。不過這沒有標準,不同公司都有不同的作法,有的公司甚至完全不寫測試。達到 100% 的覆蓋率需要耗費相當多的時間,就看技術人員評估這樣做是不是值得。

我認為用 SonarQube 的 Clean as You Code 的方式改善程式碼覆蓋率,會是比較務實的作法。也就是每次修改、新增的程式碼都通過 SonarQube 的檢查。之前的程式碼就暫時不管,但是隨著不斷的修改程式,如果有碰到之前的程式,就順便修改,加上相關的測試程式,通過 SonarQube 的檢查。專案的程式就會逐漸改善,程式碼覆蓋率會逐漸的提升。

Coverlet

GitHub 有 Coverlet 專案,此專案可建立 Code Coverage 報告。

https://github.com/coverlet-coverage/coverlet

Coverlet 有以下使用方式(多選一):

  1. VSTest engine integration - 當 Visual Studio Test Platform 執行時,找到 Coverlet Data Collector,然後由 Coverlet 負責建立 Code Coverage 報告。(功能比較少)
  2. MSBuild task integration - 整合到 MSBuild 上,也就整合到 dotnet build 的流程上。
  3. As a .NET Global tool (supports standalone integration tests) - 一個 Binary 執行檔,根據測試專案的 Assembly 建立 Code Coverage 報告。

Usage

VSTest engine integration

安裝以下 package:

dotnet add package coverlet.collector

產生 Code Coverage 報告:

dotnet test --collect:"XPlat Code Coverage"

報告會出現在類似以下的目錄(TestResults\{GUID}\coverage.cobertura.xml):

C:\\git\\coverlet\\Documentation\\Examples\\VSTest\\HelloWorld\\XUnitTestProject1\\TestResults\\bc5e983b-d7a8-4f17-8c0a-8a8831a4a891\\coverage.cobertura.xml

MSBuild task integration

安裝以下 Package:

dotnet add package coverlet.msbuild

建立 Code Coverage 報告:(Test project 會建立 coverage.json 報告)

dotnet test /p:CollectCoverage=true

As a .NET Global tool

透過 dotnet tool 安裝 coverlet 執行檔:

dotnet tool install --global coverlet.console

建立 Code Coverage 報告:

coverlet /path/to/test-assembly.dll --target "dotnet" --targetargs "test /path/to/test-project --no-build"

註:一定要指定參數 --no-build,否則會沒有資料。

MSBuild task integration 進階使用

Threshold

line, branch, method coverage 任何一項低於 80% 時會報錯:

dotnet test /p:CollectCoverage=true /p:Threshold=80

只檢測 line coverage,當低於 80% 時報錯:

dotnet test /p:CollectCoverage=true /p:Threshold=80 /p:ThresholdType=line

個別指定 coverage:

dotnet test /p:CollectCoverage=true /p:Threshold=\\"80,100,70\\" /p:ThresholdType=\\"line,branch,method\\"

根據 Attributes 排除

dotnet test /p:CollectCoverage=true /p:ExcludeByAttribute="Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute"

根據 Source Files 排除

dotnet test /p:CollectCoverage=true /p:ExcludeByFile=\\"**/dir1/class1.cs,**/dir2/*.cs,**/dir3/**/*.cs\\"
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.