本教學課程會逐步引導您完成建置範例解決方案的互動式體驗,以瞭解單元測試概念。 如果您想要使用預先建置的解決方案來遵循教學課程,請在開始之前 檢視或下載範例程序代碼 。 如需下載指示,請參閱 範例和教學課程。
本文是關於測試 .NET Core 專案。 如果您要測試 ASP.NET Core 專案,請參閱 ASP.NET Core 中的整合測試。
先決條件
- .NET 8 SDK 或更高版本。
- 選擇您喜好的文字編輯器或程式碼編輯器
建立來源專案
開啟終端機視窗。 建立名為 unit-testing-with-fsharp 的目錄來保存解決方案。 在此新目錄內,執行下列命令,為類別庫和測試專案建立新的方案檔:
dotnet new sln
接下來,建立 MathService 目錄。 下列大綱顯示到目前為止的目錄和檔案結構:
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService
將 MathService 設為目前的目錄,然後執行下列命令來建立來源專案:
dotnet new classlib -lang "F#"
您建立了一個可能失敗的數學服務實作:
module MyMath =
let squaresOfOdds xs = raise (System.NotImplementedException("You haven't written a test yet!"))
將目錄變更回 unit-testing-with-fsharp 目錄。 執行下列命令,將類別庫專案新增至方案:
dotnet sln add .\MathService\MathService.fsproj
建立測試專案
接下來,建立 MathService.Tests 目錄。 下列大綱顯示目錄結構:
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService
Source Files
MathService.fsproj
/MathService.Tests
將 MathService.Tests 目錄設為目前目錄,並使用下列命令建立新專案:
dotnet new nunit -lang "F#"
此命令會建立使用 NUnit 作為測試架構的測試專案。 產生的範本會在 MathServiceTests.fsproj中設定測試執行器:
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="NUnit" Version="4.1.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
</ItemGroup>
測試專案需要其他套件才能建立和執行單元測試。
dotnet new 在前一步中新增了 NUnit 及 NUnit 測試配接器。 現在,將 MathService 類別庫新增為專案的另一個相依性。 使用 dotnet reference add 命令:
dotnet reference add ../MathService/MathService.fsproj
您可以在 GitHub 上的 範例存放庫 中看到整個檔案。
您有下列最終解答佈局:
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService
Source Files
MathService.fsproj
/MathService.Tests
Test Source Files
MathService.Tests.fsproj
在 unit-testing-with-fsharp 目錄中執行下列命令:
dotnet sln add .\MathService.Tests\MathService.Tests.fsproj
建立第一個測試
您撰寫一個失敗的測試,讓它通過,接著重複這個過程。 開啟 UnitTest1.fs 並新增下列程式代碼:
namespace MathService.Tests
open System
open NUnit.Framework
open MathService
[<TestFixture>]
type TestClass () =
[<Test>]
member this.TestMethodPassing() =
Assert.That(true, Is.True)
[<Test>]
member this.FailEveryTime() = Assert.That(false, Is.True)
[<TestFixture>] 屬性表示包含測試的類別。
[<Test>] 屬性表示測試執行器所執行的測試方法。 從 unit-testing-with-fsharp 目錄,執行 dotnet test 來建置測試和類別庫,然後執行測試。 NUnit 測試執行器包含執行測試的程式進入點。
dotnet test 使用您建立的單元測試專案啟動測試執行器。
這兩個測試顯示了最基本的通過測試和失敗測試的結果。
My test 通過,而 Fail every time 失敗。 現在,為 squaresOfOdds 方法建立測試。
squaresOfOdds 方法會傳回屬於輸入序列之所有奇數整數值的平方的一個序列。 您可以反覆建立驗證功能的測試,而不是一次嘗試撰寫所有這些函式。 若要讓每個測試能成功通過表示您需要為方法開發所需功能。
您可以撰寫的最簡單測試是使用所有偶數呼叫 squaresOfOdds ,其中結果應該是空的整數序列。 以下是測試:
[<Test>]
member this.TestEvenSequence() =
let expected = Seq.empty<int>
let actual = MyMath.squaresOfOdds [2; 4; 6; 8; 10]
Assert.That(actual, Is.EqualTo(expected))
請注意,序列 expected 會轉換成清單。 NUnit 架構依賴許多標準 .NET 類型。 該相依性表示您的公用介面和預期結果支援 ICollection,而不是 IEnumerable。
當您執行測試時,您會看到測試失敗。 這是因為您尚未建立實作。 藉由在MathService專案中的 Library.fs 類別撰寫最簡單程式碼來讓此測試通過。
let squaresOfOdds xs =
Seq.empty<int>
在 unit-testing-with-fsharp 目錄中,再次執行 dotnet test。
dotnet test 命令會執行 MathService 項目的組建,然後執行 MathService.Tests 項目的組建。 建置這兩個項目之後,它會執行您的測試。 現在有兩個測試通過。
完成需求
既然您已通過一次測試,現在是時候撰寫更多了。 下一個簡單案例適用於只有奇數 1的序列。 數位 1 比較容易,因為 1 的平方是 1。 以下是下一個測試:
[<Test>]
member public this.TestOnesAndEvens() =
let expected = [1; 1; 1; 1]
let actual = MyMath.squaresOfOdds [2; 1; 4; 1; 6; 1; 8; 1; 10]
Assert.That(actual, Is.EqualTo(expected))
執行 dotnet test 會讓新的測試失敗。 您必須更新 squaresOfOdds 方法來處理這個新的測試。 您必須篩選序列中的所有偶數,才能通過此測試。 您可以藉由撰寫小型篩選函式並使用 Seq.filter來執行此動作:
let private isOdd x = x % 2 <> 0
let squaresOfOdds xs =
xs
|> Seq.filter isOdd
還有一步要完成:將每個奇數取平方。 從撰寫新的測試開始:
[<Test>]
member public this.TestSquaresOfOdds() =
let expected = [1; 9; 25; 49; 81]
let actual = MyMath.squaresOfOdds [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
Assert.That(actual, Is.EqualTo(expected))
您可以透過映射函數將篩選後的序列運算,以計算每個奇數的平方來修正測試:
let private square x = x * x
let private isOdd x = x % 2 <> 0
let squaresOfOdds xs =
xs
|> Seq.filter isOdd
|> Seq.map square
您已建立一個小型程式庫及其一組單元測試。 您已建構解決方案,以便新增新的套件和測試是一般工作流程的一部分。 您大部分的時間和精力都集中在解決應用程式的目標上。