次の方法で共有


dotnet テストと xUnit を使用した .NET での C# の単体テスト

このチュートリアルでは、単体テスト プロジェクトとソース コード プロジェクトを含むソリューションを構築する方法について説明します。 事前構築済みのソリューションを使用してチュートリアルに従う場合は、 サンプル コードを表示またはダウンロードします。 ダウンロード手順については、サンプルとチュートリアルを参照してください。

ソリューションを作成する

このセクションでは、ソース プロジェクトとテスト プロジェクトを含むソリューションを作成します。 完成したソリューションのディレクトリ構造は次のとおりです。

/unit-testing-using-dotnet-test
    unit-testing-using-dotnet-test.sln
    /PrimeService
        PrimeService.cs
        PrimeService.csproj
    /PrimeService.Tests
        PrimeService_IsPrimeShould.cs
        PrimeServiceTests.csproj

次の手順では、テスト ソリューションを作成する手順を示します。 1 つの手順で テスト ソリューションを作成 する手順については、「テスト ソリューションを作成するコマンド」を参照してください。

  • シェル ウィンドウを開きます。

  • 次のコマンドを実行します。

    dotnet new sln -o unit-testing-using-dotnet-test
    

    dotnet new sln コマンドは、unit-testing-using-dotnet-test ディレクトリに新しいソリューションを作成します。

  • ディレクトリを unit-testing-using-dotnet-test フォルダーに変更します。

  • 次のコマンドを実行します。

    dotnet new classlib -o PrimeService
    

    dotnet new classlib コマンドは、PrimeService フォルダーに新しいクラス ライブラリ プロジェクトを作成します。 新しいクラス ライブラリには、テストするコードが含まれます。

  • Class1.cs の名前を PrimeService.cs に変更します。

  • PrimeService.csのコードを次のコードに置き換えます。

    using System;
    
    namespace Prime.Services
    {
        public class PrimeService
        {
            public bool IsPrime(int candidate)
            {
                throw new NotImplementedException("Not implemented.");
            }
        }
    }
    

    現在、このコードでは NotImplementedException がスローされますが、このチュートリアルでは、後でこのメソッドを実装します。

  • unit-testing-using-dotnet-test ディレクトリで、次のコマンドを実行して、クラス ライブラリ プロジェクトをソリューションに追加します。

    dotnet sln add ./PrimeService/PrimeService.csproj
    
  • 次のコマンドを実行して 、PrimeService.Tests プロジェクトを作成します。

    dotnet new xunit -o PrimeService.Tests
    

    上記のコマンドは、 PrimeService.Tests ディレクトリに PrimeService.Tests プロジェクトを作成します。 テスト プロジェクトでは、テスト ライブラリとして xUnit が使用されます。 また、次の <PackageReference />要素をプロジェクト ファイルに追加して、テスト ランナーを構成します。

    • Microsoft.NET.Test.Sdk
    • xunit
    • xunit.runner.visualstudio
    • coverlet.collector
  • 次のコマンドを実行して、ソリューション ファイルにテスト プロジェクトを追加します。

    dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
    
  • PrimeService クラス ライブラリを依存関係として PrimeService.Tests プロジェクトに追加します。

    dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj
    

ソリューションを作成するコマンド

このセクションでは、前のセクションのすべてのコマンドの概要を示します。 前のセクションの手順を完了した場合は、このセクションをスキップします。

次のコマンドは、Windows マシン上にテスト ソリューションを作成します。 macOS および Unix の場合は、 ren コマンドを OS バージョンの ren に更新して、ファイルの名前を変更します。

dotnet new sln -o unit-testing-using-dotnet-test
cd unit-testing-using-dotnet-test
dotnet new classlib -o PrimeService
ren .\PrimeService\Class1.cs PrimeService.cs
dotnet sln add ./PrimeService/PrimeService.csproj
dotnet new xunit -o PrimeService.Tests
dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj
dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj

前のセクションの「 PrimeService.cs のコードを次のコードに置き換える」の手順に従います。

テストの作成

テスト 駆動開発 (TDD) の一般的なアプローチは、ターゲット コードを実装する前に (失敗した) テストを記述することです。 このチュートリアルでは、TDD アプローチを使用します。 IsPrime メソッドは呼び出し可能ですが、実装されていません。 IsPrimeのテスト呼び出しが失敗します。 TDD では、失敗することがわかっているテストを記述します。 次に、テストに合格するようにターゲット コードを更新します。 このアプローチを繰り返し、失敗したテストを記述してから、合格するようにターゲット コードを更新します。

PrimeService.Tests プロジェクトを更新します。

  • PrimeService.Tests/UnitTest1.cs を削除します。

  • PrimeService.Tests/PrimeService_IsPrimeShould.cs ファイルを作成します。

  • PrimeService_IsPrimeShould.csのコードを次のコードに置き換えます。

    using Xunit;
    using Prime.Services;
    
    namespace Prime.UnitTests.Services
    {
        public class PrimeService_IsPrimeShould
        {
            [Fact]
            public void IsPrime_InputIs1_ReturnFalse()
            {
                var primeService = new PrimeService();
                bool result = primeService.IsPrime(1);
    
                Assert.False(result, "1 should not be prime");
            }
        }
    }
    

[Fact]属性は、テスト ランナーによって実行されるテスト メソッドを宣言します。 PrimeService.Tests フォルダーから、dotnet test実行します。 dotnet テスト コマンドは、両方のプロジェクトをビルドし、テストを実行します。 xUnit テスト ランナーには、テストを実行するためのプログラム エントリ ポイントが含まれています。 dotnet test は、単体テスト プロジェクトを使用してテスト ランナーを開始します。

IsPrimeが実装されていないため、テストは失敗します。 TDD アプローチを使用して、このテストに合格するように十分なコードのみを記述します。 次のコードを使用して IsPrime を更新します。

public bool IsPrime(int candidate)
{
    if (candidate == 1)
    {
        return false;
    }
    throw new NotImplementedException("Not fully implemented.");
}

dotnet test を実行します。 テストは成功します。

さらにテストを追加する

0 と -1 の素数テストを追加します。 前の手順で作成したテスト をコピーし 、次のコードのコピーを作成して 0 と -1 をテストできます。 しかし、より良い方法があるので、それをしないでください。

var primeService = new PrimeService();
bool result = primeService.IsPrime(1);

Assert.False(result, "1 should not be prime");

パラメーターのみが変更されたときにテスト コードをコピーすると、コードの重複とテストの肥大化が発生します。 次の xUnit 属性を使用すると、同様のテストのスイートを記述できます。

  • [Theory] は、同じコードを実行するが、入力引数が異なる一連のテストを表します。
  • [InlineData] 属性は、これらの入力の値を指定します。

新しいテストを作成するのではなく、上記の xUnit 属性を適用して、単一の理論を作成します。 次のコードを置き換えます...

[Fact]
public void IsPrime_InputIs1_ReturnFalse()
{
    var primeService = new PrimeService();
    bool result = primeService.IsPrime(1);

    Assert.False(result, "1 should not be prime");
}

...次のコードを使用します。

[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
    var result = _primeService.IsPrime(value);

    Assert.False(result, $"{value} should not be prime");
}

前のコードでは、 [Theory][InlineData] 、2 未満の複数の値のテストを有効にします。 2 は最小の素数です。

クラス宣言の後、および [Theory] 属性の前に次のコードを追加します。

private readonly PrimeService _primeService;

public PrimeService_IsPrimeShould()
{
    _primeService = new PrimeService();
}

dotnet testを実行すると、2 つのテストが失敗します。 すべてのテストに合格するには、次のコードを使用して IsPrime メソッドを更新します。

public bool IsPrime(int candidate)
{
    if (candidate < 2)
    {
        return false;
    }
    throw new NotImplementedException("Not fully implemented.");
}

TDD アプローチに従って、失敗したテストをさらに追加してから、ターゲット コードを更新します。 完成したバージョンのテストライブラリの完全な実装を参照してください。

完成した IsPrime メソッドは、原始性をテストするための効率的なアルゴリズムではありません。

その他のリソース