C# xUnit入門:環境構築からテストの書き方・Assert・実行方法まで徹底解説

はじめに

C#での開発において、品質の高いコードを維持するためには単体テストの導入が不可欠です。本記事では、C#の代表的なテストフレームワークであるxUnitを使った単体テストの基本から応用まで、環境構築、テストコードの書き方、Assertの使い方、実行方法までを徹底解説します。初めてxUnitを使う方でも理解できるよう、サンプルコードと手順を交えて解説します。

1. C# xUnitとは?単体テストを始める前に知っておきたい基礎

1-1. xUnit.netの概要とC#開発で使われる理由

xUnit.netは、.NET向けのオープンソース単体テストフレームワークです。軽量でシンプルな設計により、テストの記述が直感的でわかりやすく、Visual StudioやVS Code、コマンドラインなどさまざまな環境で利用できます。また、モダンなC#開発において広く採用されているため、ライブラリやフレームワークとの互換性が高いのも特徴です。

1-2. 単体テストとは何か:手動確認との違い

単体テストとは、個々のメソッドや関数など、ソフトウェアの最小単位の動作を検証するテストです。手動確認と異なり、コードで自動化されるため、何度でも繰り返しテストが可能で、ヒューマンエラーを防ぎます。また、リファクタリングや機能追加の際に既存の動作が壊れていないかをすぐに確認できるメリットがあります。

1-3. xUnit・NUnit・MSTestの違いと選び方

xUnit、NUnit、MSTestはいずれも.NET向けのテストフレームワークですが、特徴が異なります。

  • MSTest:Microsoft公式で、Visual Studioとの統合がスムーズ。シンプルなテストに向く。

  • NUnit:豊富なアサーションと属性を持ち、柔軟なテスト記述が可能。

  • xUnit:モダンでシンプルな構文。TheoryやFixtureの利用が直感的で、CI/CDとの相性も良い。

選ぶポイントは、プロジェクトの規模、既存の開発環境、チームの慣れなどです。

1-4. xUnitでできること・できないこと

xUnitでできることは以下です。

  • メソッド単位での自動テスト実行

  • 複数パターンの入力値でのテスト

  • 例外やnullチェックの自動検証

  • テスト前後の共通処理管理(Fixture)

できないことは以下です。

  • UI操作の自動テスト(Seleniumなどを併用)

  • 外部サービスとの統合テスト(モックやスタブを活用する)

1-5. この記事で作成するテストの完成イメージ

記事内では、簡単な計算メソッドや文字列操作メソッドを例に、xUnitを用いたテストコードを作成します。完成イメージとしては、以下のように自動で検証されるテスト結果を得られる構成です。

Test1: Passed
Test2: Failed
Test3: Passed

2. C# xUnitの環境構築に必要なもの

2-1. .NET SDKのインストール確認

まずは開発環境に.NET SDKがインストールされているか確認します。コマンドプロンプトまたはターミナルで以下を実行します。

Bash
dotnet --version

バージョンが表示されればインストール済みです。未インストールの場合はからインストーラーを入手してください。

2-2. Visual Studioで始める場合の準備

Visual Studioの場合、インストール時に「.NETデスクトップ開発」ワークロードを選択します。これにより、xUnitプロジェクト作成やNuGetパッケージ管理が簡単に行えます。

2-3. VS Codeで始める場合の準備

VS Codeを使用する場合、以下を整えます。

  • C#拡張機能

  • .NET SDK

  • テストエクスプローラー拡張(VS Code用)

2-4. コマンドラインで使う場合の準備

コマンドラインだけで進める場合は、以下を確認します。

  • .NET SDKがPATHに設定済み

  • 任意のディレクトリでdotnet new xunitが使えること

2-5. xUnitでよく使うNuGetパッケージ

  • xunit:フレームワーク本体

  • xunit.runner.visualstudio:Visual Studioでのテスト実行

  • MoqFluentAssertions:モックやアサーション強化用

3. xUnitテストプロジェクトの作成手順

3-1. テスト対象のC#プロジェクトを用意する

まず、テスト対象となるC#プロジェクト(クラスライブラリやコンソールアプリ)を作成します。既存プロジェクトでも問題ありません。

3-2. xUnitテストプロジェクトを追加する

Visual Studioの場合、「新しいプロジェクトの追加」→「xUnit Test Project」を選択。
コマンドラインの場合は以下を実行します。

Bash
dotnet new xunit -n MyProject.Tests

3-3. テストプロジェクトから本体プロジェクトを参照する

テスト対象プロジェクトを参照追加します。

Bash
dotnet add MyProject.Tests reference MyProject

3-4. テスト用フォルダ・クラスの命名ルール

  • フォルダ:TestsまたはMyProject.Tests

  • クラス:対象クラス名Tests(例:CalculatorTests

  • メソッド:メソッド名_条件_期待結果(例:Add_TwoNumbers_ReturnSum

3-5. 最初のテストコードを作成する

C#
using Xunit;

public class CalculatorTests
{
[Fact]
public void Add_TwoNumbers_ReturnSum()
{
var calc = new Calculator();
int result = calc.Add(2, 3);
Assert.Equal(5, result);
}
}

4. xUnitの基本構文:Fact・Theory・InlineDataの使い方

4-1. [Fact]で単一条件のテストを書く

[Fact]属性は、固定条件でのテストを表します。引数なしでシンプルにテストケースを記述できます。

4-2. [Theory]で複数パターンのテストを書く

[Theory]は、同じ処理を複数のデータでテストする場合に使います。データはInlineDataなどで提供します。

4-3. [InlineData]でテストデータを渡す

C#
[Theory]
[InlineData(2, 3, 5)]
[InlineData(0, 0, 0)]
public void Add_VariousNumbers_ReturnSum(int a, int b, int expected)
{
var calc = new Calculator();
Assert.Equal(expected, calc.Add(a, b));
}

4-4. Arrange・Act・Assertパターンで読みやすく書く

テストコードは以下の3段階で構成すると可読性が上がります。

  1. Arrange:準備

  2. Act:操作

  3. Assert:検証

4-5. テストメソッド名の付け方と可読性のコツ

  • メソッド名_条件_期待結果形式で命名

  • テストが何を検証しているか一目で分かるようにする

5. Assertの使い方を徹底解説

5-1. Assert.Equalで値の一致を検証する

C#
Assert.Equal(expected, actual);

5-2. Assert.True・Assert.Falseで条件を検証する

C#
Assert.True(isValid);
Assert.False(isInvalid);

5-3. Assert.Null・Assert.NotNullでnullを検証する

C#
Assert.Null(obj);
Assert.NotNull(obj);

5-4. Assert.Containsでコレクションや文字列を検証する

C#
Assert.Contains("text", str);
Assert.Contains(item, list);

5-5. Assert.Throwsで例外発生を検証する

C#
Assert.Throws<ArgumentNullException>(() => method(null));

5-6. よく使うAssert一覧と使い分け

  • Equal:値が一致するか

  • True/False:条件式の真偽

  • Null/NotNull:オブジェクトの存在

  • Contains:文字列・コレクション内確認

  • Throws:例外発生確認

6. xUnitテストの実行方法

6-1. Visual Studioのテストエクスプローラーで実行する

「テストエクスプローラー」を開き、対象テストを選択して実行します。結果はGUIで確認可能です。

6-2. dotnet testコマンドで実行する

Bash
dotnet test

プロジェクト内の全テストが実行されます。

6-3. 特定のテストだけを実行する

Bash
dotnet test --filter "FullyQualifiedName~CalculatorTests.Add"

6-4. テスト結果の見方:成功・失敗・スキップ

  • Passed:成功

  • Failed:失敗

  • Skipped:実行されなかった

6-5. テストが失敗したときの原因の読み解き方

失敗メッセージとスタックトレースを確認し、期待値と実際の値、例外発生箇所を特定します。

7. 実践例:C#のメソッドをxUnitでテストする

7-1. 計算処理をテストするサンプル

C#
[Fact]
public void Multiply_TwoNumbers_ReturnProduct()
{
var calc = new Calculator();
Assert.Equal(6, calc.Multiply(2, 3));
}

7-2. 文字列処理をテストするサンプル

C#
[Fact]
public void Reverse_String_ReturnReversed()
{
var strUtil = new StringUtil();
Assert.Equal("cba", strUtil.Reverse("abc"));
}

7-3. 条件分岐をテストするサンプル

C#
[Theory]
[InlineData(10, "High")]
[InlineData(3, "Low")]
public void EvaluateNumber_ReturnCategory(int num, string expected)
{
var evaluator = new NumberEvaluator();
Assert.Equal(expected, evaluator.Evaluate(num));
}

7-4. 例外が発生する処理をテストするサンプル

C#
[Fact]
public void Divide_ByZero_ThrowsException()
{
var calc = new Calculator();
Assert.Throws<DivideByZeroException>(() => calc.Divide(10, 0));
}

7-5. 複数データで境界値をテストするサンプル

C#
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(100)]
public void ValidateBoundary_Values_ReturnTrue(int value)
{
var validator = new BoundaryValidator();
Assert.True(validator.IsValid(value));
}

8. xUnitでつまずきやすいエラーと解決方法

8-1. テストが検出されない原因と対処法

  • メソッドに[Fact][Theory]が付いていない

  • クラスがpublicでない

8-2. プロジェクト参照ができない場合の確認点

  • テストプロジェクトに本体プロジェクトの参照が追加されているか

  • 名前空間のミスがないか

8-3. NuGetパッケージ不足によるエラー

  • xunitxunit.runner.visualstudioの導入を確認

8-4. .NETのバージョン不一致によるエラー

  • プロジェクトのターゲットフレームワークを揃える

8-5. dotnet testが失敗するときのチェックリスト

  • ビルドエラーがないか

  • テストコードが正しいか

  • 参照やパッケージが正しいか

9. xUnitテストを保守しやすくする書き方

9-1. 1つのテストで検証しすぎない

1つのテストメソッドで1つの挙動だけを検証し、失敗原因を特定しやすくする。

9-2. テストデータをわかりやすく管理する

InlineDataだけでなく、MemberDataやクラス定義で整理する。

9-3. privateメソッドではなくpublicな振る舞いをテストする

外部に公開される振る舞いをテストし、内部実装に依存しない。

9-4. テストコードの重複を減らす

共通処理はメソッド化やFixtureで管理する。

9-5. 壊れにくいテストを書くための設計ポイント

  • 入力データを制御可能にする

  • 外部依存をモック化する

  • 明確な期待値を設定する

10. xUnitをさらに活用する応用トピック

10-1. テストの前処理・後処理を実装する

[Setup][TearDown]の代わりに、コンストラクタとIDisposableで前後処理を行う。

10-2. Fixtureで共通処理を管理する

共通リソースをIClassFixture<T>で管理し、重複を避ける。

10-3. モックを使った依存クラスのテスト

Moqなどを使い、外部依存の動作を模擬してテストする。

10-4. CIでxUnitテストを自動実行する

GitHub ActionsやAzure DevOpsでdotnet testを組み込み、自動実行。

10-5. カバレッジ計測へのつなげ方

coverletなどを組み合わせ、テストカバレッジを確認して品質を可視化。

まとめ

C#でのxUnitを使った単体テストは、コード品質向上やバグ早期発見に不可欠です。本記事では、環境構築からテストコード作成、Assert、実行方法、トラブルシューティングまでを網羅しました。基本を押さえつつ、Fixtureやモック、CI連携など応用技術を活用すれば、保守性の高いテスト環境を構築できます。今後は実際のプロジェクトでテストを習慣化し、信頼性の高いC#開発を目指しましょう。