- DataAttribute を継承した自作属性は、SupportsDiscoveryEnumeration() が true を返す必要がある。false だとこの設定を有効にしても展開されない
- 展開するデータはシリアライズできる値 (文字列や数値など) である必要がある
- この設定を使わずに、パッケージを xunit.v3.mtp-off に替えて従来の VSTest 方式に戻す方法もある (Visual Studio 用アダプターの既定値 true が使われる)
xUnit v2 から v3 へ移行すると、Visual Studio のテストエクスプローラーで Theory のテストに[!](未実行) の項目が残ることがあります。原因と対処法をこの記事では紹介します。
原因はテスト検出時の設定 (preEnumerateTheories) と Visual Studio のテストキャッシュです。 xunit.runner.json で設定を戻し、キャッシュを削除すると解消します。
テストエクスプローラーでテストを全件実行すると、緑 (成功) の項目と並んで、灰色の文字に[!]アイコンの項目が残ります。[!]は「未実行 (Not Run)」の印で、失敗ではありませんがテストがされていない状況です。
xUnit v3 への移行でテストランナーが変わり、Theory の検出方法が変わったことが原因です。原因は次の2つです。
xunit.v3 は Microsoft Testing Platform (MTP) に対応しており、.NET 10 SDK では global.json で MTP を有効にしないと dotnet test が通りません。 MTP では Visual Studio も xUnit v3 本体のランナーでテストを検出します。 Theory のデータ行を検出時に1件ずつ展開するかどうかは preEnumerateTheories で決まります。この設定には共通の既定値がなく、ランナーごとに既定値が違います。
Visual Studio は検出したテストを .vs\<ソリューション名>\v18\TestStore に保存しています。移行前に VSTest 用アダプターで検出した項目は、MTP に切り替えた後も削除されずに残りました。
原因1 を設定で直しても、原因2 のキャッシュがある間は[!]が消えません。そのため、対処法1 と対処法2 の両方が必要です。
[!]が出るのは [Theory] のテストだけです。データを持たない [Fact] のテストは検出も実行も 1メソッド = 1件なので、影響を受けません。
次の条件が重なると発生します。
xunit.runner.json で preEnumerateTheories を true にすると、検出時にデータ行が1件ずつ展開され、v2 の頃と同じ表示になります。
xunit.runner.json は xUnit の正式な設定ファイルで、この項目も公式ドキュメントに載っています。
1. テストプロジェクトのフォルダーに xunit.runner.json を作成する
{
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
"preEnumerateTheories": true
}
2. .csproj に、このファイルを出力フォルダーへコピーする設定を追加する
<ItemGroup>
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
3. リビルドし、検出結果を確認する
対処法1 の後も[!]が残る場合は、旧アダプターの項目がキャッシュに残っています。
TestStore フォルダーを削除すると解消します。中身はテスト一覧のキャッシュなので、消しても次回の検出で作り直されます。
<ソリューションフォルダー>\.vs\<ソリューション名>\v18\TestStore
v18 は Visual Studio 2026 の場合です。Visual Studio 2022 では v17 です。.vs フォルダーごと削除しても構いませんが、開いていたファイルなどの状態もリセットされます。
修正後、再度テストを実行します。[!]の表示が消え、テストがすべて実行された状態になります。