http://msdn.microsoft.com/zh-cn/library/ms182532.aspx
本演練將引導您完成創建、 運行和自定義一系列單元測試的托管的代碼和 Visual Studio 測試瀏覽器使用 Microsoft 單元測試框架。 您將從正處於開發過程中的 C# 項目開始,創建執行該項目代碼的測試,運行測試並檢查結果。 然后,可以更改項目代碼並重新運行測試。
本主題包含以下各節:
Fix your code and rerun your tests
Use unit tests to improve your code
說明 |
|---|
| 本演練使用 Microsoft 單元測試框架,用於托管代碼。 測試資源管理器還可以從運行測試第三方設備有適配器測試資源管理器的測試框架。 有關更多信息,請參見如何:安裝第三方單元測試框架 |
說明 |
|---|
| 有關如何從命令行運行測試的信息,請參見演練:使用命令行測試實用工具。 |
-
Bank 項目。 請參見有關創建單元測試的示例項目。
准備演練
-
打開 Visual Studio 2012。
-
在“文件”菜單上指向“新建”,然后單擊“項目”。
此時將出現“新建項目”對話框。
-
在“已安裝的模板”下單擊“Visual C#”。
-
在應用程序類型的列表中單擊“類庫”。
-
在“名稱”框中鍵入 Bank,然后單擊“確定”。
說明如果名稱“Bank”已被使用,請為該項目選擇其他名稱。
將創建新的 Bank 項目並將其顯示在解決方案資源管理器中,而且將在代碼編輯器中打開 Class1.cs 文件。
說明如果代碼編輯器中未打開 Class1.cs 文件,請在解決方案資源管理器中雙擊文件 Class1.cs 將其打開。
-
從有關創建單元測試的示例項目中復制源代碼。
-
用有關創建單元測試的示例項目中的代碼替換 Class1.cs 的原始內容。
-
將文件另存為 BankAccount.cs
-
在“生成”菜單上,單擊“生成解決方案”。
現在您有一個名為“Bank”的項目。 它包含要測試的源代碼和用於對該源代碼進行測試的工具。 Bank 的命名空間“BankAccountNS”包含公共類“BankAccount”,在以下過程中將對該類的方法進行測試。
在本快速入門,我們致力於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 項目,然后選擇添加引用...從上下文菜單。
-
在引用管理器對話框中,展開解決方案 ,然后檢查 銀行項。
我們需要測試類驗證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 BankAccountNS
測試類要求
測試類的最低要求如下所示:
-
[TestClass]屬性需要 Microsoft 單元測試框架的托管代碼中的任何類的包含要測試的資源管理器中運行單元測試方法。
-
每個所需的測試資源管理器中運行的測試方法必須與修飾[TestMethod]屬性。
您可以在不帶有單元測試項目中的幫助器類[TestMethod],並可以幫助器方法不使用修飾的測試類[TestClass]。在測試方法中,您可以使用這些非修飾類和方法,但它們不會自動運行的測試資源管理器。
在此過程中,我們將編寫單元測試以驗證行為的方法Debit方法的BankAccount類。 上面列出的方法。
通過分析測試的方法,我們確定有三個需要檢查的行為:
-
該方法將引發[ArgumentOutOfRangeException]如果貸方金額大於余額。
-
它也會引發ArgumentOutOfRangeException如果貸方金額小於零。
-
如果在簽入時 1。)和 2。都滿足時,該方法中減去從帳戶余額的金額。
在我們第一次測試,我們驗證有效的金額 (一個帳戶余額小於它的大於零) 的帳戶撤消量。
若要創建一個測試方法
-
使用添加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.Credit(debitAmount); // assert double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not credited correctly"); }
該方法很簡單。 我們建立新的BankAccount具有期初余額的對象,然后撤消有效量。 我們使用 Microsoft 單元測試框架的托管代碼AreEqual方法來驗證期末余額是否是我們所期望的結果。
測試方法要求
測試方法必須滿足以下要求:
-
該方法必須與修飾[TestMethod]屬性。
-
該方法必須返回 void。
-
該方法不能具有參數。
本部分介紹一個循環往復的過程的分析、 單元測試開發和重構功能可以怎樣幫助您使生產代碼更可靠,更有效。
分析問題
創建測試方法以確認后有效的金額是否正確扣除的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測試足以應付我們剩余的情況下進行演示。運行所有三項測試確認正確覆蓋所有情況下,在我們的原始分析。
繼續分析
但是,最后兩個測試方法都還有些人困惑。我們無法確定任何一個測試運行時,將引發測試代碼中的條件。區分兩種情況的某些方面會很有幫助。正如我們考慮的問題更多,它將成為明顯知道發生沖突的情況可能會增加我們的測試中的信心。此信息也很有可能會比較有幫助的生產機制處理時它將通過測試的方法引發的異常。所有相關,有助於方法引發時生成的詳細信息,但ExpectedException屬性不能提供此信息。.
我們再次查看該測試方法,請參閱使用這兩個條件語句ArgumentOutOfRangeException的名稱作為參數的參數的構造函數:
throw new ArgumentOutOfRangeException("amount");
從 MSDN 庫中的搜索,我們發現一個構造函數存在的報告更豐富的信息。 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方法,我們可以執行下列操作之一:
-
斷言的ActualValue異常的屬性 (第二個參數的ArgumentOutOfRangeException構造函數) 大於期初余額。此選項要求我們測試ActualValue屬性對異常的beginningBalance變量的測試方法,並且還要求,請驗證ActualValue大於零。
-
斷言 (第三個參數的構造函數) 的消息包括DebitAmountExceedsBalanceMessage中定義BankAccount類。
StringAssert.Contains Microsoft 單元測試框架中的方法,使我們能夠驗證第二個選項,而無需計算所需的第一個選項。
在修改第二次嘗試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的值是有效 (我.e.、 小於但大於 0,未捕獲異常時,因此永遠不會捕獲到該斷言的平衡。通過的測試方法。這不是很好,因為我們希望測試方法失敗不會引發異常。
第三個事實是我們的測試方法中的錯誤。若要解決此問題,我們將添加Fail斷言來處理,不會引發異常的情況下測試方法的末尾。
但是,重新測試顯示測試現在是否捕捉到正確的異常,則失敗。Catch 語句將重置該異常,該方法將繼續執行,在新的斷言失敗。若要解決此新問題,我們將添加return語句之后StringAssert。重新測試,確認我們已解決我們的問題。我們的最終版本的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);
return;
}
catch (ArgumentOutOfRangeException e)
{
// assert
StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage);
}
Assert.Fail("No exception was thrown.")
}
中的最后一節,我們做的改進我們的測試代碼的工作帶來更強健和信息性的測試方法。但更重要的是,額外的分析還帶來更好的代碼,我們所測試的項目中。
