mcpField
D
dotnet-test-frameworks

dotnet-test-frameworks

github.com/dotnetテスト・品質5.8k460 回インストール1 日前に更新
リポジトリ

dotnet-test-frameworks について

.NET 開発者やコードレビュー用ツールがテストを識別し、フレームワーク固有の規約を参照するための資料です。MSTest、xUnit、NUnit、TUnit のアサーション、ライフサイクルフック、統合テストのマーカーを扱います。

主な機能

  1. 01テストクラスとメソッドの識別
  2. 024種類のフレームワークのアサーション比較
  3. 03スキップと無視の属性を確認
  4. 04統合テストと外部依存の識別
  5. 05セットアップと後処理の規約を参照

活用シーン

  1. 01.NET コードベースのテスト分類
  2. 02フレームワーク標準の例外アサーションを提案
  3. 03テストの外部依存をレビュー
  4. 04テストのライフサイクルとスキップ動作を確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dotnet/skills --skill dotnet-test-frameworks

インストール後、Claude Code で/dotnet-test-frameworksを入力して読み込まれたか確認します。

詳細

.NET テストフレームワークリファレンス

.NET テストフレームワーク(MSTest、xUnit、NUnit、TUnit)に固有の検出パターンです。

テストファイルの識別

フレームワークテストクラスのマーカーテストメソッドのマーカー
MSTest[TestClass][TestMethod]、[DataTestMethod]
xUnit(なし — 規約ベース)[Fact]、[Theory]
NUnit[TestFixture][Test]、[TestCase]、[TestCaseSource]
TUnit(なし — 規約ベース)[Test]

フレームワーク別のアサーション API

カテゴリMSTestxUnitNUnitTUnit
等値Assert.AreEqualAssert.EqualAssert.That(x, Is.EqualTo(y))await Assert.That(x).IsEqualTo(y)
真偽値Assert.IsTrue / Assert.IsFalseAssert.True / Assert.FalseAssert.That(x, Is.True)await Assert.That(x).IsTrue() / await Assert.That(x).IsFalse()
nullAssert.IsNull / Assert.IsNotNullAssert.Null / Assert.NotNullAssert.That(x, Is.Null)await Assert.That(x).IsNull() / await Assert.That(x).IsNotNull()
例外Assert.Throws<T>() / Assert.ThrowsExactly<T>()Assert.Throws<T>()Assert.That(() => ..., Throws.TypeOf<T>())await Assert.That(() => ...).Throws<T>() / await Assert.That(() => ...).ThrowsExactly<T>()
コレクションCollectionAssert.ContainsAssert.ContainsAssert.That(col, Has.Member(x))await Assert.That(col).Contains(x)
文字列StringAssert.ContainsAssert.Contains(str, sub)Assert.That(str, Does.Contain(sub))await Assert.That(str).Contains(sub)
型Assert.IsInstanceOfTypeAssert.IsAssignableFromAssert.That(x, Is.InstanceOf<T>())await Assert.That(x).IsAssignableTo<T>()(型の完全一致チェックには await Assert.That(x).IsTypeOf<T>() を使用)
判定不能Assert.Inconclusive()[Fact(Skip)] でスキップAssert.Inconclusive()Skip.Test("reason")(実際の判定不能状態はありません)
失敗Assert.Fail()Assert.Fail()(.NET 10+)Assert.Fail()Assert.Fail()

TUnit 固有: アサーションは非同期で、必ず await する必要があります。await を忘れるとアサーションが実行されず、テストは何も通知せずに成功します。組み込みアナライザーが await の不足を警告します。複数のアサーションは .And / .Or のチェーンで組み合わせるか、Assert.Multiple() でグループ化できます。

サードパーティ製のアサーションライブラリ:Should*(Shouldly)、.Should()(FluentAssertions / AwesomeAssertions)、Verify()(Verify)。TUnit には、同じインフラストラクチャ上で FluentAssertions 形式の value.Should().BeEqualTo(...) を提供する、オプションの TUnit.Assertions.Should パッケージも付属しています。

スリープ/遅延パターン

パターン例
スレッドのスリープThread.Sleep(2000)
タスクの遅延await Task.Delay(1000)
SpinWaitSpinWait.SpinUntil(() => condition, timeout)

スキップ/無視の属性

フレームワーク属性理由付き
MSTest[Ignore][Ignore("reason")]
xUnit[Fact(Skip = "reason")](理由は必須です)
NUnit[Ignore("reason")](理由は必須です)
TUnit[Skip("reason")](理由は必須です。クラスおよびアセンブリのスコープでも有効です。例:[assembly: Skip("…")]。テスト中の動的なスキップには Skip.Test("reason") を使用します。)
条件付き#if false / #if NEVER(理由は指定できません)

例外処理 — 慣用的な代替方法

テストで例外を検証するために try / catch を使っている場合は、フレームワーク標準の代替方法を提案します。

MSTest:

// Instead of try/catch (matches exact type):
var ex = Assert.ThrowsExactly<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);

// Or (also matches derived types):
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);

xUnit:

var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.Equal("Order must contain at least one item", ex.Message);

NUnit:

var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.That(ex.Message, Is.EqualTo("Order must contain at least one item"));

TUnit:

await Assert.That(() => processor.ProcessOrder(emptyOrder))
    .Throws<InvalidOperationException>()
    .WithMessage("Order must contain at least one item");

// Or, for exact-type matching (no derived types):
await Assert.That(() => processor.ProcessOrder(emptyOrder))
    .ThrowsExactly<InvalidOperationException>();

不審な兆候 — .NET でよく見られるパターン

不審な兆候確認する内容
ファイルシステムFile.ReadAllText、File.Exists、File.WriteAllBytes、Directory.GetFiles、ハードコードされたパスを使用する Path.Combine
データベースSqlConnection、DbContext(インメモリプロバイダーを使用していないもの)、SqlCommand
ネットワークHttpMessageHandler をオーバーライドせずに使用する HttpClient、WebRequest、TcpClient
環境Environment.GetEnvironmentVariable、Environment.CurrentDirectory
許容されるものMemoryStream、StringReader、インメモリデータベースプロバイダー、カスタムの DelegatingHandler

統合テストの識別子

以下に該当するものは統合テストとして認識してください(不審度を適宜調整してください)。

  • クラス名に Integration、E2E、EndToEnd、または Acceptance が含まれる
  • [TestCategory("Integration")](MSTest)
  • [Trait("Category", "Integration")](xUnit)
  • [Category("Integration")](NUnit、TUnit)
  • プロジェクト名が .IntegrationTests または .E2ETests で終わる

セットアップ/クリーンアップメソッド

フレームワークセットアップクリーンアップ
MSTest[TestInitialize] またはコンストラクター[TestCleanup] または IDisposable.Dispose / IAsyncDisposable.DisposeAsync
xUnitコンストラクターIDisposable.Dispose / IAsyncDisposable.DisposeAsync
NUnit[SetUp][TearDown]
TUnit[Before(Test)] またはコンストラクター[After(Test)] または IDisposable.Dispose / IAsyncDisposable.DisposeAsync
MSTest(クラス)[ClassInitialize][ClassCleanup]
NUnit(クラス)[OneTimeSetUp][OneTimeTearDown]
xUnit(クラス)IClassFixture<T>フィクスチャの Dispose
TUnit(クラス)[Before(Class)][After(Class)]
TUnit(アセンブリ)[Before(Assembly)][After(Assembly)]
TUnit(セッション)[Before(TestSession)][After(TestSession)]

TUnit 固有: [BeforeEvery(Test)] / [AfterEvery(Test)](および Class / Assembly の各バリアント)は、テスト実行全体を通じて、各テスト/クラス/アセンブリごとに実行されます。グローバルな横断的フックに便利です。フックには、コンテキストオブジェクト(TestContext、ClassHookContext など)や CancellationToken を任意で渡すことができます。

コメント