本教學課程會逐步引導您完成建置範例解決方案的互動式體驗,以瞭解單元測試概念。 如果您想要使用預先建置的解決方案來遵循教學課程,請在開始之前檢視或下載範例程式代碼。 如需下載指示,請參閱 範例和教學課程。
本文是關於測試 .NET Core 專案。 如果您要測試 ASP.NET Core 專案,請參閱 ASP.NET Core 中的整合測試。
建立來源專案
開啟終端機視窗。 建立名為 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 xunit -lang "F#"
建立新專案。 這會建立使用 xUnit 作為測試連結庫的測試專案。 產生的範本會在 MathServiceTests.fsproj中設定測試執行器:
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup>
測試專案需要其他套件才能建立和執行單元測試。 在上一個步驟中 dotnet new
新增 xUnit 和 xUnit 執行器。 現在,將 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
MathServiceTests.fsproj
在 dotnet sln add .\MathService.Tests\MathService.Tests.fsproj
目錄中執行 。
建立第一個測試
您撰寫一個失敗的測試,讓它通過,接著重複這個過程。 開啟 Tests.fs,並新增下列程式代碼:
[<Fact>]
let ``My test`` () =
Assert.True(true)
[<Fact>]
let ``Fail every time`` () = Assert.True(false)
[<Fact>]
屬性表示測試執行器所執行的測試方法。 從 unit-testing-with-fsharp 執行命令來建置測試和類別庫,然後運行測試。 xUnit 測試執行器包含執行測試的程式進入點。
dotnet test
使用您建立的單元測試專案啟動測試執行器。
這兩個測試顯示了最基本的通過測試和失敗測試的結果。
My test
通過,而 Fail every time
失敗。 現在,為 squaresOfOdds
方法建立測試。
squaresOfOdds
方法會傳回屬於輸入序列之所有奇數整數值的平方的一個序列。 您可以反覆建立驗證功能的測試,而不是一次嘗試撰寫所有這些函式。 使每個測試通過意味著為方法創建必要的功能。
我們可以撰寫的最簡單測試是用所有偶數調用 squaresOfOdds
,其中回傳結果應該是空的整數序列。 以下是測試:
[<Fact>]
let ``Sequence of Evens returns empty collection`` () =
let expected = Seq.empty<int>
let actual = MyMath.squaresOfOdds [2; 4; 6; 8; 10]
Assert.Equal<Collections.Generic.IEnumerable<int>>(expected, actual)
您的測試失敗。 您尚未創建實作。 在可運作的 MathService
類別中撰寫最簡單的程式代碼,讓此測試通過:
let squaresOfOdds xs =
Seq.empty<int>
在 unit-testing-with-fsharp 目錄中,再次執行 dotnet test
。
dotnet test
命令會執行 MathService
項目的組建,然後執行 MathService.Tests
項目的組建。 建置這兩個項目之後,它會執行此單一測試。 它通過了。
完成所有需求
既然您已通過一次測試,現在是時候撰寫更多了。 下一個簡單案例適用於只有奇數 1
的序列。 數位 1 比較容易,因為 1 的平方是 1。 以下是下一個測試:
[<Fact>]
let ``Sequences of Ones and Evens returns Ones`` () =
let expected = [1; 1; 1; 1]
let actual = MyMath.squaresOfOdds [2; 1; 4; 1; 6; 1; 8; 1; 10]
Assert.Equal<Collections.Generic.IEnumerable<int>>(expected, actual)
執行 dotnet test
會運行您的測試,並顯示新的測試失敗。 現在,更新 squaresOfOdds
方法來處理這個新的測試。 您可以篩選序列中的所有偶數,讓此測試通過。 您可以藉由撰寫小型篩選函式並使用 Seq.filter
來執行此動作:
let private isOdd x = x % 2 <> 0
let squaresOfOdds xs =
xs
|> Seq.filter isOdd
還有一個步驟要走:平方每個奇數。 從撰寫新的測試開始:
[<Fact>]
let ``SquaresOfOdds works`` () =
let expected = [1; 9; 25; 49; 81]
let actual = MyMath.squaresOfOdds [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
Assert.Equal(expected, actual)
您可以透過映射函數將篩選後的序列運算,以計算每個奇數的平方來修正測試:
let private square x = x * x
let private isOdd x = x % 2 <> 0
let squaresOfOdds xs =
xs
|> Seq.filter isOdd
|> Seq.map square
您已建立一個小型程式庫及其一組單元測試。 您已建構解決方案,以便新增新的套件和測試是一般工作流程的一部分。 您大部分的時間和精力都集中在解決應用程式的目標上。