共用方式為


使用 dotnet test 和 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

下列指示提供建立測試解決方案的步驟。 要在單一步驟中建立測試解決方案,請參閱 建立測試解決方案的命令

  • 開啟終端機視窗。

  • 執行下列命令:

    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 命令更新為 的 ren OS 版本,以重新命名檔案:

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 test 命令會建置專案並執行測試。 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] 啟用測試數個小於二的值。 二是最小的質數。

在類別宣告之後和[Theory]屬性之前新增下列程式碼:

private readonly PrimeService _primeService;

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

執行 dotnet test,其中兩個測試失敗。 若要讓所有測試都通過,請使用下列程式碼更新 IsPrime 方法:

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

遵循 TDD 方法,新增更多失敗的測試,然後更新目標程式代碼。 請參閱測試的完成版本以及程式庫的完整實施。

已完成的IsPrime方法不是測試質數性的高效演算法。

其他資源