使用 TUnit 和 .NET 進行 C# 單元測試

本教學課程會逐步引導您完成建置範例解決方案的互動式體驗,以瞭解單元測試概念。

本文是關於測試 .NET Core 專案。 如果您要測試 ASP.NET Core 專案,請參閱 ASP.NET Core 中的整合測試。

Prerequisites

  • .NET 10 SDK 或更新版本。
  • 您偏好的文字編輯器或程式碼編輯器。

TUnit 完全建置於 Microsoft.Testing.Platform (MTP),且不支援 VSTest。 本教學使用 MTP 模式dotnet test,需 .NET 10 SDK。

建立來源專案

開啟終端機視窗。 建立一個名為 unit-testing-using-tunit 的目錄來存放解決方案。 在此新目錄內,執行下列命令,為類別庫和測試專案建立新的方案檔:

dotnet new sln

接下來,建立 PrimeService 目錄。 下列大綱顯示到目前為止的目錄和檔案結構:

/unit-testing-using-tunit
    unit-testing-using-tunit.slnx
    /PrimeService

將 PrimeService 設為目前的目錄,然後執行下列命令來建立來源專案:

dotnet new classlib

將 Class1.cs 重新命名為 PrimeService.cs。 您建立一個 PrimeService 類別的失敗實作:

using System;

namespace Prime.Services
{
    public class PrimeService
    {
        public bool IsPrime(int candidate)
        {
            throw new NotImplementedException("Please create a test first.");
        }
    }
}

切換回 unit-testing-using-tunit 目錄。 執行下列命令,將類別庫專案新增至方案:

dotnet sln add PrimeService/PrimeService.csproj

建立測試專案

接下來,建立 PrimeService.Tests 目錄。 下列大綱顯示目錄結構:

/unit-testing-using-tunit
    unit-testing-using-tunit.slnx
    /PrimeService
        Source Files
        PrimeService.csproj
    /PrimeService.Tests

TUnit 專案範本不包含在 .NET SDK 中。 請使用以下指令安裝:

dotnet new install TUnit.Templates

將目錄變更為 PrimeService.Tests 目錄,然後使用下列命令建立新專案:

dotnet new TUnit

Note

模板短名稱具有大小寫區分。 使用 TUnit,而不是 tunit。

dotnet new 指令會建立一個使用 TUnit 作為測試函式庫的測試專案。 產生的 PrimeService.Tests.csproj 檔案是一個可執行專案,會參考 TUnit 套件(版本號可能不同):

<PropertyGroup>
  <ImplicitUsings>enable</ImplicitUsings>
  <Nullable>enable</Nullable>
  <OutputType>Exe</OutputType>
  <TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
  <PackageReference Include="TUnit" Version="1.*" />
</ItemGroup>

該 TUnit 套件包含測試框架、斷言函式庫和 MTP 測試執行器,因此專案不需要其他測試套件。 範本還新增了範例測驗。 請刪除 PrimeService.Tests 目錄中所有 .cs 檔案和 Data 目錄,因為這個教學會用自己的測試取代它們。

現在,將 PrimeService 類別庫新增為專案的另一個相依性。 使用 dotnet reference add 命令:

dotnet reference add ../PrimeService/PrimeService.csproj

下列大綱顯示最終解決方案配置:

/unit-testing-using-tunit
    unit-testing-using-tunit.slnx
    /PrimeService
        Source Files
        PrimeService.csproj
    /PrimeService.Tests
        Test Source Files
        PrimeService.Tests.csproj

在 unit-testing-using-tunit 目錄中執行以下指令:

dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj

設定 dotnet test 的 MTP 模式

因為 TUnit 不支援 VSTest,TUnit 必須以 MTP 模式執行。 在 unit-testing-using-tunit 目錄中,建立一個包含以下內容的 global.json 檔案:

{
    "test": {
        "runner": "Microsoft.Testing.Platform"
    }
}

欲了解更多資訊,請參閱 dotnet 測試的 MTP 模式。

建立第一個測試

您撰寫了一個未通過的測試,使其通過,然後重複此過程。 在 PrimeService.Tests 目錄中,建立一個包含以下程式碼的 PrimeService_IsPrimeShould.cs 檔案:

namespace Prime.UnitTests.Services
{
    using Prime.Services;

    public class PrimeService_IsPrimeShould
    {
        private readonly PrimeService _primeService = new();

        [Test]
        public async Task IsPrime_InputIs1_ReturnFalse()
        {
            var result = _primeService.IsPrime(1);

            await Assert.That(result).IsFalse();
        }
    }
}

屬性 [Test] 表示方法為測試方法。 TUnit 不需要在類別上設定屬性。 TUnit 的斷言是非同步的,因此測試方法會回傳 Task,並等待 Assert.That。 這個 TUnit 套件會為其命名空間新增全域 using 指令,因此檔案不需要它們。

Note

using Prime.Services;指令是刻意放在命名空間內的。 MTP 會在專案的根命名空間中(亦即 PrimeService.Tests)產生測試應用程式的入口點。 該命名空間會隱藏 PrimeService 類別,使位於檔案頂端的 using 指示詞無法看見它,但不會對命名空間內的 using 指示詞隱藏它。

儲存此檔案並執行 dotnet test 命令來建置測試和類別庫,並執行測試。 TUnit 測試專案包含執行測試的程式入口點。 dotnet test 用你建立的單元測試專案啟動測試應用程式。

您的測試失敗。 您尚未建立執行方案。 在可運作的 PrimeService 類別中撰寫最簡單的程式代碼,讓測試通過:

public bool IsPrime(int candidate)
{
    if (candidate == 1)
    {
        return false;
    }
    throw new NotImplementedException("Please create a test first.");
}

在 unit-testing-using-tunit 目錄中,再次執行 dotnet test 。 dotnet test 命令會執行 PrimeService 項目的組建,然後執行 PrimeService.Tests 項目的組建。 建置這兩個項目之後,它會執行這個單一測試。 它通過了。

新增更多功能

現在您已經通過了一次測試,是時候寫更多了。 關於質數,有一些其他的特殊情況:0、-1。 您可以透過添加 [Test] 屬性來新增測試,但這樣做很快就會變得乏味。 TUnit 提供 [Arguments] 屬性,用於建立一套執行相同程式碼但輸入參數不同的測試套件。

不要建立新的測試,請套用此屬性來建立單一數據驅動測試。 將 IsPrime_InputIs1_ReturnFalse 方法用下列程式碼取代。 數據驅動測試是一種方法,用來測試數個小於二的數值,而二是一個最低的質數。

[Test]
[Arguments(-1)]
[Arguments(0)]
[Arguments(1)]
public async Task IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
    var result = _primeService.IsPrime(value);

    await Assert.That(result).IsFalse();
}

執行 dotnet test,其中兩個測試會失敗。 若要讓所有測試都通過,請變更 if 檔案中 IsPrime 方法開頭的 子句:

if (candidate < 2)

持續迭代,在主函式庫中加入更多測試和程式碼。

您建置了一個小型程式庫,以及該程式庫的一組單元測試。 您也已建構解決方案,讓新增套件和測試是標準工作流程的一部分。 您大部分的時間和精力都集中在解決應用程式的目標上。

也請參閱