逐步解說:建立和執行單元測試
本逐步解說將會逐步導引您使用 Microsoft Visual Studio 2010 來建立、執行和自訂一系列的測試。 您可以從開發中的 C# 專案開始,建立執行其程式碼的測試、執行測試,並檢查結果。 然後,您可以修改專案程式碼並重新執行測試。
![]() |
---|
如需如何從命令列執行測試的資訊,請參閱逐步解說:使用命令列測試公用程式。 |
在這個逐步解說中,您將完成下列工作:
準備一個能在逐步解說中使用的「銀行帳戶」專案。
開啟現有專案。
建立公用和私用方法的單元測試
針對程式碼執行這些測試。
找出和修正測試中的錯誤。
找出和修正程式碼中的錯誤。
必要條件
- Woodgrove Bank 專案。 請參閱用於建立單元測試的範例專案。
準備逐步解說
若要準備逐步解說
開啟 Visual Studio 2010 Premium。
在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。
[新增專案] 對話方塊隨即出現。
在 [已安裝的範本] 下,按一下 [Visual C#]。
在應用程式類型清單中,按一下 [類別庫]。
在 [名稱] 方塊中,輸入 Bank,然後按一下 [確定]。
注意事項
如果已經有專案使用 "Bank" 這個名稱,就請為專案選擇另一個名稱。
新的 Bank 專案會建立並顯示在 [方案總管] 中,並於 [程式碼編輯器] 中開啟 Class1.cs 檔。
注意事項
如果 Class1.cs 檔並未在 [程式碼編輯器] 中開啟,請按兩下 [方案總管] 中的 Class1.cs 檔加以開啟。
複製用於建立單元測試的範例專案中的原始程式碼。
以用於建立單元測試的範例專案中的程式碼取代 Class1.cs 的原始內容。
在 [建置] 功能表上,按一下 [建置方案]。
現在您已經有一個名為 Bank 的專案。 其中包含要測試的原始程式碼和用來測試它的工具。 Bank 的命名空間 BankAccountNS,包含了公用類別 BankAccount,您將會在下列程序中測試其方法。
建立單元測試
必要條件:遵循準備逐步解說程序中的步驟。
若要建立單元測試
如果 Class1.cs 檔並未在 [程式碼編輯器] 中開啟,請在 [方案總管] 中按兩下 Bank 專案中的 Class1.cs 檔。
在 Class1.cs 檔案的 [BankAccount] 類別中,捲動至 [Debit()] 方法。
以滑鼠右鍵按一下 [Debit()] 方法,然後選取 [建立單元測試]。
[建立單元測試] 對話方塊隨即出現。
在 [目前的選取範圍] 下,會有樹狀結構顯示包含 [BankAccount] 類別之組件的類別和成員階層架構。 您可以使用這個頁面為這些成員的任何選取範圍產生單元測試,並選擇一個測試專案,以便將產生的單元測試放置到其中。
在這個樹狀結構中,只有選取這個 [Debit()] 方法。 維持該項目的選取狀態,並且再選取 [Credit()] 方法。
對於 [輸出專案],選取 [建立新 Visual C# 測試專案]。
按一下 [設定]。
[測試產生設定] 對話方塊隨即出現。 在 [命名設定] 下,您可以變更測試檔案、測試類別和測試方法在產生時的命名方式。 在 [一般] 下,您可以變更測試產生的其他設定。 維持這些設定的預設值,然後按一下 [確定]。
在 [建立單元測試] 對話方塊中,按一下 [確定]。
[新增測試專案] 對話方塊隨即出現。
接受預設名稱,並按一下 [建立]。
如此就會建立名為 TestProject1 的專案,此專案會出現在 [方案總管] 中。
TestProject1 中會加入名為 BankAccountTest.cs 的檔案,其中含有一個測試類別。 這個類別中會填入 (Populate) 一個 TestContext 屬性及數個方法,用來測試 [Debit()] 和 [Credit()] 方法。
注意事項
每個測試方法都會自動獲得 TestMethod() 屬性的指派。 每個測試都對應至所要測試之「受測程式碼」(Code Under Test) 中的單一方法。 測試方法都會位於被指派 TestClass() 屬性的測試類別中。
在 BankAccountTest.cs 中,指定所要測試之變數的值。 捲動至 [DebitTest] 方法,您會在該處看到數行 // TODO,它們會指出所要設定的變數。
若要知道要用於 DebitTest 方法的值,請開啟 Class1.cs 檔並捲動至 [Main] 方法。 請注意,客戶名稱會初始化為 [Mr. Bryan Walton],帳戶餘額會初始化為 [11.99],[Credit] 方法會以 [5.77] 的參數來呼叫,[Debit] 方法則會以 [11.22] 的參數來呼叫。 因此,如果帳戶在一開始時具有 [11.99] 的 [餘額],呼叫 [Debit] 方法並傳遞 [11.22] 就應該會得到 [0.77] 的新 [餘額]。
注意事項
在這個逐步解說後面的步驟中,您會用到這個預期的 [Balance] 值 (0.77)。
在 BankAccountTest.cs 檔案中捲動至 [DebitTest] 方法。
設定下列的值:
BankAccount target = new BankAccount("Mr. Bryan Walton", 11.99); double amount = 11.22;
在 [CreditTest] 方法中,將 ("Mr. Bryan Walton", 11.99) 加入至新的 BankAccount。
儲存 BankAccountTest.cs 檔案。
如此便會建立一個包含 Bank 專案之測試的原始程式碼檔案。 現在您已經完成準備工作,可以針對 Bank 專案的程式碼,在 [BankAccountTest] 類別中執行測試。
執行和自訂單元測試
必要條件:執行建立單元測試程序中的步驟。
若要執行和自訂單元測試
在 [測試] 功能表上,按一下 [視窗],然後選取 [測試檢視]。
[測試檢視] 視窗隨即顯示。
以滑鼠右鍵按一下 [DebitTest],然後按一下 [執行選取範圍]。
如果 [測試結果] 視窗尚未開啟,則該視窗現在就會予以開啟。 [DebitTest] 測試便開始執行。
當測試正在執行時,在 [測試結果] 視窗的 [結果] 資料行中,測試狀態會顯示為 [執行中]。 當測試回合完成後,測試的結果就會變更為 [結果不明]。
在 [測試結果] 視窗中,以滑鼠右鍵按一下代表測試的資料列,然後按一下 [檢視測試結果詳細資料]。
[測試結果詳細資料] 頁面會顯示錯誤訊息:「Assert.Inconclusive 失敗。 無法驗證不傳回值的方法」。若要設法建立成功的測試,請先找到並評估這個 [Assert] 陳述式 (Statement)。
若要找到包含此 [Assert] 陳述式的測試方法,請開啟 BankAccountTest.cs 檔案並捲動至 [DebitTest()] 方法。
Assert 陳述式位於 [DebitTest] 方法的最後一行, 內容如下:
Assert.Inconclusive("A method that does not return a value cannot be verified.");
將這個 Assert 陳述式標記為註解。
如果現在執行測試,就會產生 [成功] 的結果,不過這是因為沒有任何項目受到測試的原因。 您必須加入程式碼,以測試結果是否如預期一樣。 將下列陳述式加入至 [DebitTest] 的結尾:
Assert.AreEqual((System.Convert.ToDouble(0.77)), target.Balance, 0.05);
這個陳述式會對預期結果 (0.77) 與呼叫 [BankAccount] 類別之 [Balance] 方法的實際結果進行比較。 如果兩個值並不相等,[Assert] 就會傳回 [False],如此測試就會失敗。
注意事項
這個 [Assert] 陳述式包含了第三個參數,具有值為 0.05 的 [delta]。 在此 [Assert.AreEqual] 方法的多載中,delta 參數是必要的。這個參數會補償浮點型別 (像是 [Doubles]) 中的固有捨入錯誤。
您已執行過產生之 [BankAccountTest] 測試類別的 [DebitTest] 方法,請注意此方法需要變更,並且著手進行這些變更。 現在您已完成測試應用程式中 [Debit] 方法之正確性的準備工作。
執行單元測試和修正您的程式碼
必要條件:執行執行和自訂單元測試程序中的步驟。
若要執行單元測試和修正您的程式碼
再次執行 Debit 測試:在 BankAccountTest.cs 檔案中,以滑鼠右鍵按一下 [DebitTest()] 方法,然後按一下 [執行測試]。
當測試正在執行時,在 [測試結果] 視窗的 [結果] 資料行中,測試狀態會顯示為 [執行中]。 當測試回合完成後,測試的結果就會變更為 [失敗]。
在 [測試結果] 視窗中,以滑鼠右鍵按一下代表測試的資料列,然後按一下 [檢視測試結果詳細資料]。
如此就會開啟 [結果詳細資料] 頁面,其中顯示錯誤訊息:「Assert.AreEqual 失敗。 預期值 <0.77> 和實際值 <23.21> 之間的預期差異沒有大於 <0.05>」。 這些數目似乎表示錯誤的算術運算。 這是因為 [BankAccountTest] 類別的 [DebitTest] 方法在測試 [BankAccount] 類別的 [Debit] 方法時,會從檢查 [Debit] 方法開始。
開啟 Class1.cs 檔案並捲動至 [Debit] 方法。
請注意下列設定:
m_balance += amount;
雖然 [Debit] 方法應該是減少餘額,但這項設定卻會將金額加入至餘額。 請依下列所示進行修改:
m_balance -= amount;
再度執行 [Debit] 測試。
[測試結果] 視窗的 [結果] 資料行便會對 [DebitTest] 顯示為 [成功]。
注意事項
由於執行測試會以無訊息模式建置專案,您並不需要在變更來源程式碼後重新建置測試專案。
您已經建立一個可以運作的單元測試,而且已經透過此測試來找出並修正程式碼中的錯誤。
為私用方法建立和執行單元測試
必要條件:執行執行單元測試和修正您的程式碼程序中的步驟。
若要為私用方法建立和執行單元測試
開啟 Bank 專案中的 Class1.cs 檔案。
以滑鼠右鍵按一下 [FreezeAccount()] 方法,並選取 [建立單元測試]。
[建立單元測試] 對話方塊隨即出現。
在顯示的樹狀結構中,只有選取這個 [FreezeAccount()] 方法。
(選擇性) 按一下 [篩選],然後清除 [顯示非公用項目]。 請注意此時 [FreezeAccount()] 方法便會從 BankAccount 類別的子方法清單中移除。 再按一次 [篩選],然後選取 [顯示非公用項目],即可重新顯示 [FreezeAccount()] 方法。
確定已選取 [FreezeAccount()] 方法,然後按一下 [確定]。
這個步驟會建立新的私用存取子檔案,名稱為 Bank.accessor。 檔案中包含特殊的存取子方法,可供測試用來直接呼叫 BankAccount 類別中的私用方法。 您可以在 [方案總管] 的 [測試參考] 資料夾中看到這個新檔案。
開啟 BankAccountTest.cs 檔案並捲動至 [FreezeAccountTest()] 方法。
將 [FreezeAccountTest()] 方法的程式碼變更如下。 只表示已變更或新的區域:
public void FreezeAccountTest() { BankAccount_Accessor target = new BankAccount_Accessor("Mr. Bryan Walton", 11.99); // TODO: Initialize to an appropriate value target.FreezeAccount(); // Assert.Inconclusive("A method that does not return a value cannot be verified."); bool creditAccount = false; // False means account could be credited: Fail test. // Try to credit account try { target.Credit(1.00); } catch (System.Exception) { // Threw exception. FreezeAccount worked correctly: Pass test. creditAccount = true; } // Assert fails if 'creditAccount' condition is false. Fail test. Assert.IsTrue(creditAccount, "Was able to credit account."); }
執行 FreezeAccountTest 測試。
在 [測試結果] 視窗中的 [結果] 資料行中,最後的測試狀態將顯示為 [成功]。 這是預期的結果,因為此測試會在呼叫 [FreezeAccount()] 方法凍結帳戶之後,呼叫 [Credit()] 方法。
您已經加入一個私用方法、建立了該方法的新單元測試並且執行過這個測試。 您可以執行這個測試好幾次,以其他臨界值使用於 balance 變數 (如 15.00)。
後續步驟
當您在組件中針對程式碼執行測試時,您可以看到以收集程式碼涵蓋範圍資料所測試之專案程式碼的比例。 如需詳細資訊,請參閱逐步解說:執行測試並檢視程式碼涵蓋範圍。
您可以在命令列上執行測試,而不使用 Visual Studio。 如需詳細資訊,請參閱逐步解說:使用命令列測試公用程式。
如果您使用 Visual Studio 2010 Ultimate,您可以建立負載測試,以使用單元測試找出壓力和效能問題。