逐步解說:建立和執行單元測試

本逐步解說將會逐步導引您使用 Microsoft Visual Studio 2010 來建立、執行和自訂一系列的測試。 您可以從開發中的 C# 專案開始,建立執行其程式碼的測試、執行測試,並檢查結果。 然後,您可以修改專案程式碼並重新執行測試。

注意事項注意事項

如需如何從命令列執行測試的資訊,請參閱逐步解說:使用命令列測試公用程式

在這個逐步解說中,您將完成下列工作:

  • 準備一個能在逐步解說中使用的「銀行帳戶」專案。

  • 開啟現有專案。

  • 建立公用和私用方法的單元測試

  • 針對程式碼執行這些測試。

  • 找出和修正測試中的錯誤。

  • 找出和修正程式碼中的錯誤。

必要條件

準備逐步解說

若要準備逐步解說

  1. 開啟 Visual Studio 2010 Premium。

  2. 在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。

    [新增專案] 對話方塊隨即出現。

  3. 在 [已安裝的範本] 下,按一下 [Visual C#]。

  4. 在應用程式類型清單中,按一下 [類別庫]。

  5. 在 [名稱] 方塊中,輸入 Bank,然後按一下 [確定]。

    注意事項注意事項

    如果已經有專案使用 "Bank" 這個名稱,就請為專案選擇另一個名稱。

    新的 Bank 專案會建立並顯示在 [方案總管] 中,並於 [程式碼編輯器] 中開啟 Class1.cs 檔。

    注意事項注意事項

    如果 Class1.cs 檔並未在 [程式碼編輯器] 中開啟,請按兩下 [方案總管] 中的 Class1.cs 檔加以開啟。

  6. 複製用於建立單元測試的範例專案中的原始程式碼。

  7. 用於建立單元測試的範例專案中的程式碼取代 Class1.cs 的原始內容。

  8. 在 [建置] 功能表上,按一下 [建置方案]。

現在您已經有一個名為 Bank 的專案。 其中包含要測試的原始程式碼和用來測試它的工具。 Bank 的命名空間 BankAccountNS,包含了公用類別 BankAccount,您將會在下列程序中測試其方法。

建立單元測試

必要條件:遵循準備逐步解說程序中的步驟。

若要建立單元測試

  1. 如果 Class1.cs 檔並未在 [程式碼編輯器] 中開啟,請在 [方案總管] 中按兩下 Bank 專案中的 Class1.cs 檔。

  2. 在 Class1.cs 檔案的 [BankAccount] 類別中,捲動至 [Debit()] 方法。

  3. 以滑鼠右鍵按一下 [Debit()] 方法,然後選取 [建立單元測試]。

    [建立單元測試] 對話方塊隨即出現。

    在 [目前的選取範圍] 下,會有樹狀結構顯示包含 [BankAccount] 類別之組件的類別和成員階層架構。 您可以使用這個頁面為這些成員的任何選取範圍產生單元測試,並選擇一個測試專案,以便將產生的單元測試放置到其中。

    在這個樹狀結構中,只有選取這個 [Debit()] 方法。 維持該項目的選取狀態,並且再選取 [Credit()] 方法。

  4. 對於 [輸出專案],選取 [建立新 Visual C# 測試專案]。

  5. 按一下 [設定]。

    [測試產生設定] 對話方塊隨即出現。 在 [命名設定] 下,您可以變更測試檔案、測試類別和測試方法在產生時的命名方式。 在 [一般] 下,您可以變更測試產生的其他設定。 維持這些設定的預設值,然後按一下 [確定]。

  6. 在 [建立單元測試] 對話方塊中,按一下 [確定]。

    [新增測試專案] 對話方塊隨即出現。

  7. 接受預設名稱,並按一下 [建立]。

    如此就會建立名為 TestProject1 的專案,此專案會出現在 [方案總管] 中。

    TestProject1 中會加入名為 BankAccountTest.cs 的檔案,其中含有一個測試類別。 這個類別中會填入 (Populate) 一個 TestContext 屬性及數個方法,用來測試 [Debit()] 和 [Credit()] 方法。

    注意事項注意事項

    每個測試方法都會自動獲得 TestMethod() 屬性的指派。 每個測試都對應至所要測試之「受測程式碼」(Code Under Test) 中的單一方法。 測試方法都會位於被指派 TestClass() 屬性的測試類別中。

  8. 在 BankAccountTest.cs 中,指定所要測試之變數的值。 捲動至 [DebitTest] 方法,您會在該處看到數行 // TODO,它們會指出所要設定的變數。

  9. 若要知道要用於 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)。

  10. 在 BankAccountTest.cs 檔案中捲動至 [DebitTest] 方法。

  11. 設定下列的值:

    BankAccount target = new BankAccount("Mr. Bryan Walton", 11.99);
    double amount = 11.22;
    
  12. 在 [CreditTest] 方法中,將 ("Mr. Bryan Walton", 11.99) 加入至新的 BankAccount。

  13. 儲存 BankAccountTest.cs 檔案。

如此便會建立一個包含 Bank 專案之測試的原始程式碼檔案。 現在您已經完成準備工作,可以針對 Bank 專案的程式碼,在 [BankAccountTest] 類別中執行測試。

執行和自訂單元測試

必要條件:執行建立單元測試程序中的步驟。

若要執行和自訂單元測試

  1. 在 [測試] 功能表上,按一下 [視窗],然後選取 [測試檢視]。

    [測試檢視] 視窗隨即顯示。

  2. 以滑鼠右鍵按一下 [DebitTest],然後按一下 [執行選取範圍]。

    如果 [測試結果] 視窗尚未開啟,則該視窗現在就會予以開啟。 [DebitTest] 測試便開始執行。

    當測試正在執行時,在 [測試結果] 視窗的 [結果] 資料行中,測試狀態會顯示為 [執行中]。 當測試回合完成後,測試的結果就會變更為 [結果不明]。

  3. 在 [測試結果] 視窗中,以滑鼠右鍵按一下代表測試的資料列,然後按一下 [檢視測試結果詳細資料]。

  4. [測試結果詳細資料] 頁面會顯示錯誤訊息:「Assert.Inconclusive 失敗。 無法驗證不傳回值的方法」。若要設法建立成功的測試,請先找到並評估這個 [Assert] 陳述式 (Statement)。

  5. 若要找到包含此 [Assert] 陳述式的測試方法,請開啟 BankAccountTest.cs 檔案並捲動至 [DebitTest()] 方法。

  6. Assert 陳述式位於 [DebitTest] 方法的最後一行, 內容如下:

    Assert.Inconclusive("A method that does not return a value cannot be verified.");
    

    將這個 Assert 陳述式標記為註解。

  7. 如果現在執行測試,就會產生 [成功] 的結果,不過這是因為沒有任何項目受到測試的原因。 您必須加入程式碼,以測試結果是否如預期一樣。 將下列陳述式加入至 [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] 方法之正確性的準備工作。

執行單元測試和修正您的程式碼

必要條件:執行執行和自訂單元測試程序中的步驟。

若要執行單元測試和修正您的程式碼

  1. 再次執行 Debit 測試:在 BankAccountTest.cs 檔案中,以滑鼠右鍵按一下 [DebitTest()] 方法,然後按一下 [執行測試]。

    當測試正在執行時,在 [測試結果] 視窗的 [結果] 資料行中,測試狀態會顯示為 [執行中]。 當測試回合完成後,測試的結果就會變更為 [失敗]。

  2. 在 [測試結果] 視窗中,以滑鼠右鍵按一下代表測試的資料列,然後按一下 [檢視測試結果詳細資料]。

    如此就會開啟 [結果詳細資料] 頁面,其中顯示錯誤訊息:「Assert.AreEqual 失敗。 預期值 <0.77> 和實際值 <23.21> 之間的預期差異沒有大於 <0.05>」。 這些數目似乎表示錯誤的算術運算。 這是因為 [BankAccountTest] 類別的 [DebitTest] 方法在測試 [BankAccount] 類別的 [Debit] 方法時,會從檢查 [Debit] 方法開始。

  3. 開啟 Class1.cs 檔案並捲動至 [Debit] 方法。

  4. 請注意下列設定:

    m_balance += amount;
    

    雖然 [Debit] 方法應該是減少餘額,但這項設定卻會將金額加入至餘額。 請依下列所示進行修改:

    m_balance -= amount;
    
  5. 再度執行 [Debit] 測試。

    [測試結果] 視窗的 [結果] 資料行便會對 [DebitTest] 顯示為 [成功]。

    注意事項注意事項

    由於執行測試會以無訊息模式建置專案,您並不需要在變更來源程式碼後重新建置測試專案。

您已經建立一個可以運作的單元測試,而且已經透過此測試來找出並修正程式碼中的錯誤。

為私用方法建立和執行單元測試

必要條件:執行執行單元測試和修正您的程式碼程序中的步驟。

若要為私用方法建立和執行單元測試

  1. 開啟 Bank 專案中的 Class1.cs 檔案。

  2. 以滑鼠右鍵按一下 [FreezeAccount()] 方法,並選取 [建立單元測試]。

    [建立單元測試] 對話方塊隨即出現。

    在顯示的樹狀結構中,只有選取這個 [FreezeAccount()] 方法。

  3. (選擇性) 按一下 [篩選],然後清除 [顯示非公用項目]。 請注意此時 [FreezeAccount()] 方法便會從 BankAccount 類別的子方法清單中移除。 再按一次 [篩選],然後選取 [顯示非公用項目],即可重新顯示 [FreezeAccount()] 方法。

  4. 確定已選取 [FreezeAccount()] 方法,然後按一下 [確定]。

    這個步驟會建立新的私用存取子檔案,名稱為 Bank.accessor。 檔案中包含特殊的存取子方法,可供測試用來直接呼叫 BankAccount 類別中的私用方法。 您可以在 [方案總管] 的 [測試參考] 資料夾中看到這個新檔案。

  5. 開啟 BankAccountTest.cs 檔案並捲動至 [FreezeAccountTest()] 方法。

  6. 將 [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.");
    }
    
  7. 執行 FreezeAccountTest 測試。

    在 [測試結果] 視窗中的 [結果] 資料行中,最後的測試狀態將顯示為 [成功]。 這是預期的結果,因為此測試會在呼叫 [FreezeAccount()] 方法凍結帳戶之後,呼叫 [Credit()] 方法。

您已經加入一個私用方法、建立了該方法的新單元測試並且執行過這個測試。 您可以執行這個測試好幾次,以其他臨界值使用於 balance 變數 (如 15.00)。

後續步驟

當您在組件中針對程式碼執行測試時,您可以看到以收集程式碼涵蓋範圍資料所測試之專案程式碼的比例。 如需詳細資訊,請參閱逐步解說:執行測試並檢視程式碼涵蓋範圍

您可以在命令列上執行測試,而不使用 Visual Studio。 如需詳細資訊,請參閱逐步解說:使用命令列測試公用程式

如果您使用 Visual Studio 2010 Ultimate,您可以建立負載測試,以使用單元測試找出壓力和效能問題。

逐步解說:建立和執行包含單元測試的負載測試

請參閱

工作

用於建立單元測試的範例專案