逐步解說:建立並執行 UWP 應用程式的單元測試
本文說明如何在 Visual Studio 中對通用 Windows 平台 (UWP) 應用程式進行單元測試。 Visual Studio 提供適用於 C#、Visual Basic 和 C++ 的 UWP 單元測試專案範本。 如需開發 UWP 應用程式的詳細資訊,請參閱 UWP 應用程式入門。
本文將逐步解說在 UWP 應用程式中建立 C# 類別並進行單元測試的範例。 此範例會使用測試驅動開發來撰寫驗證特定行為的測試,然後撰寫通過測試的程式碼。
建立和執行單元測試專案
下列程序說明如何建立及執行 UWP 應用程式的單元測試專案。
建立 UWP 單元測試專案
在 Visual Studio 的 [開始] 視窗上,選擇 [建立新專案]。
在 [建立新的專案] 頁面的搜尋方塊中,輸入「單元測試」。 範本清單會篩選至單元測試專案。
選取 C# 或 Visual Basic 的 [單元測試應用程式 (通用 Windows)] 範本,然後選取 [下一步]。
選擇性地變更專案或方案的名稱和位置,然後選取 [建立]。
選擇性地變更目標和最低平台版本,然後選取 [確定]。
Visual Studio 會建立測試專案,並在 Visual Studio [方案總管] 中開啟它。
在 Visual Studio 的 [開始] 視窗上,選擇 [建立新專案]。
在 [建立新的專案] 頁面的搜尋方塊中,輸入「單元測試」。 範本清單會篩選至單元測試專案。
選取 C# 或 Visual Basic 的 [單元測試應用程式 (通用 Windows)] 範本,然後選取 [下一步]。
選擇性地變更專案或方案的名稱和位置,然後選取 [建立]。
選擇性地變更目標和最低平台版本,然後選取 [確定]。
Visual Studio 會建立測試專案,並在 Visual Studio [方案總管] 中開啟它。
編輯專案的應用程式資訊清單
在 [方案總管] 中,以滑鼠右鍵按一下 Package.appxmanifest 檔案並選取 [開啟]。
在資訊清單設計工具中,選取 [功能] 索引標籤。
在 [功能] 清單中,選取程式碼和單元測試所需的功能。 例如,如果您的程式碼及其單元測試需要存取網際網路,請選取 [網際網路] 核取方塊。
只選取讓單元測試正常運作所需的功能。
新增程式碼以對 UWP 應用程式進行單元測試
在 Visual Studio 程式碼編輯器中,編輯單元測試程式碼檔案,以新增測試所需的判斷提示和邏輯。 如需範例,請參閱本文稍後的對 C# 類別進行單元測試。
使用測試總管執行單元測試
使用 [測試總管] 建置方案與執行單元測試。
在 Visual Studio [測試] 功能表上,選取 [測試總管]。 [測試總管] 視窗隨即開啟。
在 [測試總管] 中,選取 [全部執行] 圖示。 您必須使用 [全部執行] 來探索 UWP 專案中的測試。
方案會建置執行並進行單元測試。 測試執行之後,測試會出現在 [測試總管] 測試清單中,其中包含結果和持續時間的相關資訊。
此外,您也可以在 [測試總管] 中選取個別測試,並以滑鼠右鍵按一下 [執行] 或 [偵錯] 測試,或 [前往測試] 以開啟測試程式碼。 從頂端功能表中,您可以將測試分組、將測試新增至播放清單,或開啟測試選項。
使用 [測試總管] 建置方案與執行單元測試。
在 Visual Studio [測試] 功能表上,選取 [測試總管]。 [測試總管] 視窗隨即開啟。
在 [測試總管] 中,選取 [全部執行] 圖示。 您必須使用 [全部執行] 來探索 UWP 專案中的測試。
方案會建置執行並進行單元測試。 測試執行之後,測試會出現在 [測試總管] 測試清單中,其中包含結果和持續時間的相關資訊。
此外,您也可以在 [測試總管] 中選取個別測試,並以滑鼠右鍵按一下 [執行] 或 [偵錯] 測試,或 [前往測試] 以開啟測試程式碼。 從頂端功能表中,您可以將測試分組、將測試新增至播放清單,或開啟測試選項。
對 C# 類別進行單元測試
一組穩定而良好的單元測試,可讓您確信並未在變更程式碼時引入錯誤。 下列範例會逐步解說如何在 UWP 應用程式中建立 C# 類別的單元測試。 此範例會使用測試驅動開發來撰寫驗證特定行為的測試,然後撰寫通過測試的程式碼。
在 Maths 程式碼專案的範例中,Rooter 類別會實作函式,以計算數字的預估平方根。 RooterTests 專案會對 Rooter 類別進行單元測試。
建立方案和專案
建立 UWP 應用程式專案:
- 在 Visual Studio 的 [檔案] 功能表上,選取 [新增專案]。
- 在 [建立新專案] 頁面上,於 [搜尋] 方塊中輸入空白應用程式,然後選取 C# [空白應用程式 (通用 Windows)] 專案範本。
- 在 [設定新專案] 頁面上,將專案命名為 Maths,然後選取 [建立]。
- 選擇性地變更目標和最低平台版本,然後選取 [確定]。 Visual Studio 隨即建立專案,並在 [方案總管] 中開啟該專案。
建立單元測試專案:
- 在 [方案總管] 中,以滑鼠右鍵按一下 Maths 方案,然後選擇 [新增]>[新增專案]。
- 在 [新增專案] 頁面上,於 [搜尋] 方塊中輸入單元測試,然後選取 C# [單元測試應用程式 (通用 Windows)] 專案範本。
- 將測試專案命名為 RooterTests,然後選取 [建立]。
- 選擇性地變更目標和最低平台版本,然後選取 [確定]。 RooterTests 專案會出現在 [方案總管] 中的 Maths 方案底下。
驗證測試總管中執行的測試
Assert 類別提供數個靜態方法,可讓您在測試方法中用來驗證結果。
在 [方案總管] 中,選取 RooterTests 專案中的 UnitTest1.cs 檔案。
將下列程式碼插入
TestMethod1
:[TestMethod] public void TestMethod1() { Assert.AreEqual(0, 0); }
在 [測試總管] 中,選取 [執行所有測試]。
測試專案會建置並執行,而測試會出現在 [通過的測試] 底下。 右側的 [群組摘要] 窗格提供測試的詳細資料。
將類別新增至應用程式專案
在 [方案總管] 中,於 Maths 專案上按一下滑鼠右鍵,然後選取 [新增]>[類別]。
將類別檔案命名為 Rooter.cs,然後選取 [新增]。
在程式碼編輯器中,將下列程式碼新增至 Rooter.cs 檔案中的
Rooter
類別:public Rooter() { } // estimate the square root of a number public double SquareRoot(double x) { return 0.0; }
Rooter
類別會宣告建構函式和SquareRoot
評估工具方法。SquareRoot
方法是測試基本測試設定的最小實作。將
internal
關鍵字變更為Rooter
類別宣告中的public
,讓測試程式碼可以存取它。public class Rooter
在 [方案總管] 中,於 Maths 專案上按一下滑鼠右鍵,然後選取 [新增]>[類別]。
將類別檔案命名為 Rooter.cs,然後選取 [新增]。
在程式碼編輯器中,將下列程式碼新增至 Rooter.cs 檔案中的
Rooter
類別:public Rooter() { } // estimate the square root of a number public double SquareRoot(double x) { return 0.0; }
Rooter
類別會宣告建構函式和SquareRoot
評估工具方法。SquareRoot
方法是測試基本測試設定的最小實作。將
public
關鍵字新增至Rooter
類別宣告,讓測試程式碼可以存取它。public class Rooter
將測試專案的參考新增至應用程式專案
在 [方案總管] 中 ,以滑鼠右鍵按一下 RooterTests 專案,然後選取 [新增]>[參考]。
在 [參考管理員 - RooterTests] 對話方塊中,展開 [專案],然後選取 Maths 專案。
選取 [確定]。
在
using Microsoft.VisualStudio.TestTools.UnitTesting;
行之後,將下列using
陳述式新增至 UnitTest.cs:using Maths;
在 [方案總管] 中 ,以滑鼠右鍵按一下 RooterTests 專案,然後選取 [新增]>[參考]。
在 [參考管理員 - RooterTests] 對話方塊中,展開 [專案],然後選取 Maths 專案。
選取 [確定]。
在行之後
using Microsoft.VisualStudio.TestTools.UnitTesting;
,將下列using
陳述式新增至 UnitTest.cs:using Maths;
新增使用應用程式函式的測試
將下列測試方法新增至 UnitTest.cs:
[TestMethod] public void BasicTest() { Maths.Rooter rooter = new Rooter(); double expected = 0.0; double actual = rooter.SquareRoot(expected * expected); double tolerance = .001; Assert.AreEqual(expected, actual, tolerance); }
新的測試會出現在 [方案總管] 和 [測試總管] 的 [未執行測試] 節點中。
若要避免「承載包含兩個或多個具有相同目的地路徑的檔案」錯誤,請在 [方案總管] 中展開 Maths 專案下的 [屬性] 節點,並刪除 Default.rd.xml 檔案。
儲存所有檔案。
執行測試
在 [測試總管] 中,選取 [執行所有測試] 圖示。 接著方案就會建置並執行測試然後通過。
在 [測試總管] 中,選取 [執行所有測試] 圖示。 接著方案就會建置並執行測試然後通過。
如果您在執行測試時收到「重複的實體」錯誤,請從測試專案中刪除執行階段指示詞檔案 Properties\Default.rd.xml
,然後重新嘗試。
您已設定測試和應用程式專案,並確認您可以執行可在應用程式專案中呼叫函式的測試。 現在您可以撰寫實際的測試和程式碼。
新增測試並讓測試通過
最好不要變更已通過的測試。 請改為新增測試。 藉由一次新增一個測試來開發程式碼,並確定所有測試都會在每個反覆項目之後通過。
將名為
RangeTest
的新測試新增至 UnitTest.cs:[TestMethod] public void RangeTest() { Rooter rooter = new Rooter(); for (double v = 1e-6; v < 1e6; v = v * 3.2) { double expected = v; double actual = rooter.SquareRoot(v*v); double tolerance = expected/1000; Assert.AreEqual(expected, actual, tolerance); } }
執行 RangeTest 測試,並確認它失敗。
提示
在測試驅動開發中,您會在撰寫測試之後立即執行測試。 此做法有助於避免撰寫永遠不會失敗的測試這種易犯的錯誤。
修正您的應用程式程式碼,讓新的測試通過。 在 Rooter.cs 中,變更
SquareRoot
函式,如下所示:public double SquareRoot(double x) { double estimate = x; double diff = x; while (diff > estimate / 1000) { double previousEstimate = estimate; estimate = estimate - (estimate * estimate - x) / (2 * estimate); diff = Math.Abs(previousEstimate - estimate); } return estimate; }
在 [測試總管] 中,選取 [執行所有測試] 圖示。 現在三項測試都會成功。
將名為
RangeTest
的新測試新增至 UnitTest.cs:[TestMethod] public void RangeTest() { Rooter rooter = new Rooter(); for (double v = 1e-6; v < 1e6; v = v * 3.2) { double expected = v; double actual = rooter.SquareRoot(v*v); double tolerance = expected/1000; Assert.AreEqual(expected, actual, tolerance); } }
執行 RangeTest 測試,並確認它失敗。
提示
在測試驅動開發中,您會在撰寫測試之後立即執行測試。 此做法有助於避免撰寫永遠不會失敗的測試這種易犯的錯誤。
修正您的應用程式程式碼,讓新的測試通過。 在 Rooter.cs 中,變更
SquareRoot
函式,如下所示:public double SquareRoot(double x) { double estimate = x; double diff = x; while (diff > estimate / 1000) { double previousEstimate = estimate; estimate = estimate - (estimate * estimate - x) / (2 * estimate); diff = Math.Abs(previousEstimate - estimate); } return estimate; }
在 [測試總管] 中,選取 [執行所有測試] 圖示。 現在三項測試都會成功。
重構程式碼
在本節中,您會重構應用程式和測試程式碼,然後重新執行測試,以確定程式碼仍然會通過。
簡化平方根估計
在 Rooter.cs 中,藉由變更下列這一行來簡化
SquareRoot
函式中的中央計算:estimate = estimate - (estimate * estimate - x) / (2 * estimate);
目標
estimate = (estimate + x/estimate) / 2.0;
執行所有測試,以確定您並未引入迴歸。 測試應該會通過。
移除重複的測試程式碼
RangeTest
方法會對傳遞至 tolerance
方法之 Assert 變數的分母採用硬式編碼。 如果您打算新增更多使用相同容錯計算的測試,請在數個位置使用硬式編碼值,讓程式碼更難維護。 相反地,您可以將私人協助程式方法新增至 UnitTest1
類別以計算容錯值,然後從 RangeTest
呼叫該方法。
若要新增協助程式方法,請在 UnitTest.cs 中:
將下列方法新增至
UnitTest1
班級:private double ToleranceHelper(double expected) { return expected / 1000; }
在
RangeTest
中,變更下列這一行:double tolerance = expected/1000;
目標
double tolerance = ToleranceHelper(expected);
執行 RangeTest 測試以確定它仍然會通過。
提示
如果您將協助程式方法新增至測試類別,且您不希望協助程式方法出現在 [測試總管] 的清單中,請勿將 TestMethodAttribute 屬性新增至該方法。
下一步
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應