はじめに
今回はdotnet test
でコードカバレッジを収集する際にExcludeFromCodeCoverageAttribute
を用いて対象外にする設定をする方法を紹介したいと思います。
learn.microsoft.com
コードカバレッジ収集について
コードカバレッジ収集はcoverlet.collector
を利用している前提で話をすすめていきます。
https://www.nuget.org/packages/coverlet.collector
$ dotnet add package coverlet.collector
# 必須 : --collect:"XPlat Code Coverage" # 任意: --results-directoryにより出力先フォルダを指定できる。出力先ディレクトリ/<GUID>/coverage.cobertura.xmlのように出力され、GUIDは必ずついてくる $ dotnet test --collect:"XPlat Code Coverage" --results-directory:"./Result" Determining projects to restore... 復元対象のすべてのプロジェクトは最新です。 // ... テスト実行を開始しています。お待ちください... 合計 1 個のテスト ファイルが指定されたパターンと一致しました。 成功! -失敗: 0、合格: 3、スキップ: 0、合計: 3、期間: 13 ms - TestProject1.dll (net8.0) 添付ファイル: <ProjectRoot>/Result/bb585210-e6ba-45a6-a15f-4d86d782b69a/coverage.cobertura.xml
詳細については以下の記事で触れているので、利用方法が不明な方は参照してみてください。
www.hanachiru-blog.com
コードカバレッジの収集対象外に設定する
対象外にしたいクラスまたは構造体に対して[ExcludeFromCodeCoverage]
を付与してあげます。
using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] public class Program { public static void Main() { Console.WriteLine("Hello World!"); } }
クラスまたは構造体にこの属性を配置すると、そのクラスまたは構造体のすべてのメンバーがコード カバレッジ情報のコレクションから除外されます。
ExcludeFromCodeCoverageAttribute クラス (System.Diagnostics.CodeAnalysis) | Microsoft Learn
また実装をみてみると、公式ドキュメントには記述がありませんでしたがクラス・構造体以外にも以下に対応していそうでした。
Assembly
Class
Struct
Constructor
Method
Property
Event
namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false, AllowMultiple = false)] public sealed class ExcludeFromCodeCoverageAttribute : Attribute { public ExcludeFromCodeCoverageAttribute() { } /// <summary>Gets or sets the justification for excluding the member from code coverage.</summary> public string? Justification { get; set; } } }
実験
実際にclass
に対して付与してみて、コードカバレッジの変化を見てみます。
$ tree . ├── Program.cs ├── SampleHelper.cs ├── SampleConsoleNet8.csproj
using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] public class Program { public static void Main() { Console.WriteLine("Hello World!"); } }
namespace SampleConsoleNet8; public static class SampleHelper { public static string GetSampleString() { return "Sample String"; } public static string GetSampleString2(string text) { if (string.IsNullOrEmpty(text)) { return ""; } return $"Sample String: {text}"; } }
coberturaの変化
やや分かりづらいですが、Program
に関する記述がまるっとなくなっています。
ExcludeFromCodeCoverageAttribute
を付与しない場合
<?xml version="1.0" encoding="utf-8"?> <coverage line-rate="0.6666" branch-rate="0.5" version="1.9" timestamp="1729422662" lines-covered="8" lines-valid="12" branches-covered="1" branches-valid="2"> <sources> <source>----/SampleConsoleNet8/</source> </sources> <packages> <package name="SampleConsoleNet8" line-rate="0.6666" branch-rate="0.5" complexity="4"> <classes> <class name="Program" filename="Program.cs" line-rate="0" branch-rate="1" complexity="1"> <methods> <method name="Main" signature="()" line-rate="0" branch-rate="1" complexity="1"> <!-- 省略 --> </methods> <lines> <!-- 省略 --> </lines> </class> <class name="SampleConsoleNet8.SampleHelper" filename="SampleHelper.cs" line-rate="0.8887999999999999" branch-rate="0.5" complexity="3"> <methods> <!-- 省略 --> </method> </methods> <lines> <!-- 省略 --> </lines> </class> </classes> </package> </packages> </coverage>
ExcludeFromCodeCoverageAttribute
付与した場合
<?xml version="1.0" encoding="utf-8"?> <coverage line-rate="0.8887999999999999" branch-rate="0.5" version="1.9" timestamp="1729422682" lines-covered="8" lines-valid="9" branches-covered="1" branches-valid="2"> <sources> <source>/</source> </sources> <packages> <package name="SampleConsoleNet8" line-rate="0.8887999999999999" branch-rate="0.5" complexity="3"> <classes> <class name="SampleConsoleNet8.SampleHelper" filename="----/SampleHelper.cs" line-rate="0.8887999999999999" branch-rate="0.5" complexity="3"> <methods> <!-- 省略 --> </methods> <lines> <!-- 省略 --> </lines> </class> </classes> </package> </packages> </coverage>