摘自:http://msdn.microsoft.com/zh-cn/library/ms182532.aspx
版本:VS2012
本演練將創建將引導您逐步完成,運行,并且,自定義一系列單元測試使用 Microsoft 單元測試托管代碼的結構,Visual Studio 測試管理器。 您將從正處于開發過程中的 C# 項目開始,創建執行該項目代碼的測試,運行測試并檢查結果。 然后,可以更改項目代碼并重新運行測試。
本主題包含以下各節:
![]() |
---|
本演練使用 Microsoft 單元測試托管代碼的結構。 測試資源管理器還可以從運行單元測試框架具有 Test 資源管理器適配器的第三方測試。 有關更多信息,請參閱如何:安裝第三方單元測試框架。 |
![]() |
---|
有關如何從命令行運行測試的信息,請參見演練:使用命令行測試實用工具。 |
-
bank 項目。 請參見用于創建單元測試的示例項目。
準備演練
-
打開 Visual Studio 2012。
-
在“文件”菜單上指向“新建”,然后單擊“項目”。
此時將出現“新建項目”對話框。
-
在“已安裝的模板”下單擊“Visual C#”。
-
在應用程序類型的列表中單擊“類庫”。
-
在“名稱”框中鍵入 Bank,然后單擊“確定”。
說明
如果名稱“Bank”已被使用,請為該項目選擇其他名稱。
將創建新的 Bank 項目并將其顯示在解決方案資源管理器中,而且將在代碼編輯器中打開 Class1.cs 文件。
說明
如果代碼編輯器中未打開 Class1.cs 文件,請在解決方案資源管理器中雙擊文件 Class1.cs 將其打開。
-
從用于創建單元測試的示例項目中復制源代碼。
-
用用于創建單元測試的示例項目中的代碼替換 Class1.cs 的原始內容。
-
該文件保存為 BankAccount.cs
-
在“生成”菜單上,單擊“生成解決方案”。
現在您有一個名為“Bank”的項目。 它包含要測試的源代碼和用于對該源代碼進行測試的工具。 Bank 的命名空間“BankAccountNS”包含公共類“BankAccount”,在以下過程中將對該類的方法進行測試。
本快速啟動,我們討論 Debit 方法。,在提取貨幣帳戶并包含以下代碼時,debit 方法調用:
// method under test public void Debit(double amount) { if(amount > m_balance) { throw new ArgumentOutOfRangeException("amount"); } if (amount < 0) { throw new ArgumentOutOfRangeException("amount"); } m_balance += amount; }
系統必備:按照準備演練過程中的步驟執行操作。
創建單元測試項目
-
在 文件 菜單中,選擇 添加,然后選擇 新項目…。
-
在新項"對話框中,展開 已安裝,展開 Visual C#,然后選擇 測試。
-
從模板列表,選擇 單元測試項目。
-
在 名稱 框中,輸入 BankTest,然后選擇 確定。
BankTests 項目添加到 銀行 解決方案。
-
在 BankTests 項目中,添加對 銀行 解決方案。
在解決方案資源管理器中,BankTests 項目的 SELECT 引用 從上下文菜單中選擇 添加引用 ...。
-
在引用管理器對話框中,展開 解決方案 然后檢查 銀行 項目。
我們需要驗證的 BankAccount 選件類測試選件類。 我們可以使用由項目模板生成的 UnitTest1.cs,但是,我們應為文件和類更具聲明性的名稱。 我們可以通過對解決方案資源管理器中重命名文件執行于在一個步驟。
對選件類重命名文件
在解決方案資源管理器中,選擇在 BankTests 項目的 UnitTest1.cs 文件。 從上下文菜單中,選擇 重命名,然后將該文件重命名為 BankAccountTests.cs。 選中詢問的對話框的 是 您是否在項目中重命名對代碼元素“UnitTest1”。 此換步選件類的名稱。BankAccountTest。
BankAccountTests.cs 文件現在包含以下代碼:
// unit test code using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BankTests { [TestClass] public class BankAccountTests { [TestMethod] public void TestMethod1() { } } }
添加 using 語句添加到項目測試
我們還可以添加 using 語句添加到選件類并將到項目測試,而無需使用完全限定名。 在選件類文件的頂部,添加:
using BankAccountNS
測試選件類要求
測試選件類的最低要求如下:
-
[TestClass] 屬性在 Microsoft 單元測試框架所需的為托管代碼對于包含單元測試方法要運行的測試資源管理器的任何選件類。
-
每個測試需要測試管理器運行必須具有 [TestMethod]屬性的方法。
可以讓沒有 [TestClass] 屬性在部件的其他選件類測試項目,并且,可以讓其他方法測試沒有 [TestMethod] 屬性的選件類。 可以使用這些其他選件類,并在方法的測試方法。
在此過程中,我們將編寫單元測試方法驗證 BankAccount 選件類的 Debit 方法的行為。 方法上面列出。
通過分析方法下測試,我們確定需要簽出至少有三種行為:
-
方法引發 [ArgumentOutOfRangeException],如果超出信用保存與該平衡大。
-
如果超出信用保存小于零,小于它還引發 ArgumentOutOfRangeException。
-
如果在 1.) 和 2. 的檢查) 滿意,方法從帳戶余額減去此數量。
在我們第一個測試,我們驗證是否比帳戶余額小于,并且大于零) 的有效的量 (一提取從該帳戶的正確數量。
創建測試方法
-
添加 using BankAccountNS; 語句添加到 BankAccountTests.cs 文件。
-
將下面的方法添加到該 BankAccountTests 選件類:
// unit test code [TestMethod] public void Debit_WithValidAmount_UpdatesBalance() { // arrange double beginningBalance = 11.99; double debitAmount = 4.55; double expected = 7.44; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly"); }
方法非常簡單。 我們設置與開頭平衡的新 BankAccount 對象并提取有效的數量。 我們使用 Microsoft 單元測試托管代碼 AreEqual 方案的結構可以驗證期末余額什么是我們需要。
測試方法要求
測試方法必須滿足以下要求:
-
必須用 [TestMethod] 特性修飾方法。
-
該方法必須返回 void。
-
方法不能有參數。
分析測試結果
測試結果包含描述錯誤的消息。 為 AreEquals 方法,則會顯示您預期內容的 (Expected<entity_PLACEHOLDERXXX>參數),以及實際接收 ( Actual<YYY> 參數)。 我們需要從開始拒絕該平衡的平衡,而是由量取款增加而增加。
debit 代碼的復審表示,單元測試在發現 bug 成功。 則應當減去時,量取款添加到帳戶余額它。
更正 bug
若要更正此錯誤,請替換行
m_balance += amount;
with
m_balance -= amount;
重新運行測試
在測試資源管理器中,選擇 全部運行 重新運行測試。 紅色-綠色條啟用綠色,并且,測試移到 通過的測試 組。
本節描述迭代過程如何分析,單元測試,開發,并重構可幫助您的生產代碼更加可靠和有效。
分析問題
在創建測試方法后確認有效的量 Debit 方法都將正確扣除,可以轉向在我們的原始分析的其余的情況:
-
方法引發 ArgumentOutOfRangeException,如果超出信用保存與該平衡大。
-
如果超出信用保存小于零,小于它還引發 ArgumentOutOfRangeException。
創建測試方法
在創建測試方法的第一次嘗試解決這些問題是有為:
//unit test method [TestMethod] [ExpectedException(typeof(ArgumentOutOfRangeException))] public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange() { // arrange double beginningBalance = 11.99; double debitAmount = -100.00; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert is handled by ExpectedException }
我們使用 ExpectedExceptionAttribute 屬性斷言正確的已引發異常。 除非 ArgumentOutOfRangeException 引發,特性使測試失敗。 運行帶有正和負 debitAmount 值的測試暫時然后修改該方法受測引發一般 ApplicationException,該數量小于零演示是測試能否正常工作的更小時。 若要測試用例,則會提取的此數量小于該平衡時大,我們需要執行的所有:
-
創建新測試方法命名 Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange。
-
將 Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange 的方法主體。新方法。
-
與該平衡設置 debitAmount 為數字大。
運行測試
運行不同的值的兩個方法 debitAmount 的說明,是否足以測試處理我們剩余的大小寫。 運行所有三種測試確認在我們的原始分析的全部大小寫正確地介紹。
繼續該分析
但是,最后兩個測試方法還一些令人焦慮。 我們無法確定在代碼來適應下測試,則引發任何測試運行時。 區分兩個條件某種方法很有用。 我們更考慮該問題,變得顯而易見知道哪個條件違反了將增加我們中的 confidence 測試。 它由方法引發測試時,此信息也可能對該生成的結構很有用的異常。 生成更多信息,則方法將引發是幫助所有問題,但是,ExpectedException 屬性無法提供此信息。
查看方法下再次測試,我們同時看到條件語句使用接受參數的名稱作為參數的一個 ArgumentOutOfRangeException 構造函數:
throw new ArgumentOutOfRangeException("amount");
從 MSDN Library 中搜索,我們查看存在構造函數報告豐富的信息。 ArgumentOutOfRangeException (String, Object, String) 包括參數、參數值和一個用戶定義的消息的名稱。 我們可以重構方法下測試使用此構造函數。 更好,可以使用公開的類型成員指定錯誤。
測試代碼的重構
我們首先定義錯誤消息的兩個常數。選件類范圍:
// class under test public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance"; public const string DebitAmountLessThanZeroMessage = "Debit amount less than zero";
我們然后修改在 Debit 方法的兩個條件語句:
// method under test // ... if (amount > m_balance) { throw new ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage); } if (amount < 0) { throw new ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage); } // ...
重構測試方法
在我們測試方法中,我們首先移除 ExpectedException 屬性。 在原地,我們捕獲時引發的異常并驗證它是否能在正確的條件語句是否引發了。 但是,我們現在必須決定在兩個選項卡之間驗證我們剩余的情況。 例如在 Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange 方法,可以執行下列操作之一:
-
斷言異常 ( ArgumentOutOfRangeException 構造函數的第二個參數的 ActualValue 屬性) 的開頭平衡大。 此選項要求我們測試異常的 ActualValue 屬性的測試方法 beginningBalance 變量,并需要然后驗證 ActualValue 大于零。
-
斷言消息 (構造函數的第三個參數) 在 BankAccount 選件類包括定義的 DebitAmountExceedsBalanceMessage。
Microsoft 單元測試的 StringAssert.Contains 方法測試框架使我們驗證第二個選項,而無需第一個選項的計算。
在修改 Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange 的第二個嘗試可能類似于:
[TestMethod] public void Debit_WhenAmountIsGreaterThanBalance_ShouldThrowArgumentOutOfRange() { // arrange double beginningBalance = 11.99; double debitAmount = 20.0; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);\ // act try { account.Debit(debitAmount); } catch (ArgumentOutOfRangeException e) { // assert StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage); } }
重測,復蓋,并重新分析
我們再次測試不同的值時的測試方法,我們會遇到以下情況:
-
如果我們查看與該平衡大的正確的錯誤使用 debitAmount,Contains 斷言通過,異常,將忽略,所以測試方法傳遞。 這是我們需的行為。
-
如果要使用 debitAmount,斷言失敗,因為錯誤的錯誤返回。 如果要在方法引入一個臨時 ArgumentOutOfRange 異常在另一個點測試代碼路徑,斷言還會失敗。 這也是好。
-
如果 debitAmount 值是有效的 (即,小于平衡,但大于零,不捕獲到異常,因此,斷言它不會被捕獲。 測試方法傳遞。 這不是好,因為我們希望測試方法失敗,如果未引發異常。
第三種情況是在我們的 bug 測試方法。 若要嘗試解決該問題,我們添加 Fail 斷言在測試方法結束時處理不會引發異常的情況。
但是,重新測試,表示測試現在未通過,如果正確的捕獲到異常。 catch 語句重置異常,而方法繼續執行,會在新的 assert。 若要解決新的問題,我們在 StringAssert之后添加一個 return 語句。 再次測試來確認我們解決了問題。 我們的 Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange 的定稿如下所示:
[TestMethod] public void Debit_WhenAmountIsGreaterThanBalance_ShouldThrowArgumentOutOfRange() { // arrange double beginningBalance = 11.99; double debitAmount = 20.0; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);\ // act try { account.Debit(debitAmount); } catch (ArgumentOutOfRangeException e) { // assert StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage); return; } Assert.Fail("No exception was thrown.") }
在此最后部分,工作完成改進我們測試代碼生成更加可靠和信息性測試方法。 但更重要的是,多余的分析也會改進。我們的項目的測試代碼。
文章列表