共用方式為


教程:使用 Visual Studio 和 .NET 測試 .NET 類別庫

本教學課程示範如何將測試專案新增至方案,將單元測試自動化。

先決條件

本教學課程適用於您在 使用 Visual Studio 建立 .NET 類別庫中建立的解決方案。

建立單元測試專案

單元測試會在開發和發佈期間提供自動化軟體測試。 MSTest 是您可以從中選擇的三個測試架構之一。 其他則是 xUnitnUnit

  1. 啟動 Visual Studio。

  2. 開啟您在 ClassLibraryProjects建立 .NET 類別庫時所建立的 解決方案。

  3. 將名為 「StringLibraryTest」 的新單元測試專案新增至方案。

    1. [方案總管] 中對方案按右鍵,然後選取 [新增>專案]

    2. 在 [[新增專案] 頁面上,於搜尋方塊中輸入 mstest。 從 [語言] 列表中選擇 C#Visual Basic,然後從 [平臺] 清單中選擇 [所有平臺]

    3. 選擇 MSTest 測試項目 樣本,然後選擇 [下一步]

    4. [設定新專案] 頁面上,於 [專案 名稱] 方塊中輸入 StringLibraryTest。 然後選擇 [下一步]

    5. 在 [其他資訊] 頁面上,選取 [Framework] 方塊中的 [.NET 8]。 然後選擇 建立

  4. Visual Studio 會建立專案,並使用下列程式代碼在程式碼視窗中開啟類別檔案。 如果未顯示您要使用的語言,請變更頁面頂端的語言選取器。

    namespace StringLibraryTest;
    
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
    
    Imports Microsoft.VisualStudio.TestTools.UnitTesting
    
    Namespace StringLibraryTest
        <TestClass>
        Public Class UnitTest1
            <TestMethod>
            Sub TestSub()
    
            End Sub
        End Class
    End Namespace
    

    單元測試範本所建立的原始程式碼會執行下列動作:

    在標有 [TestClass] 的測試類別中,每個標有 [TestMethod] 的方法都會在單元測試執行時自動執行。

新增專案參考

若要讓測試專案與 StringLibrary 類別一起工作,請在 StringLibraryTest 專案中加入一個參考,以將其連結至 StringLibrary 專案。

  1. [方案總管]中,以滑鼠右鍵點擊 StringLibraryTest 專案的 相依性 節點,然後從操作功能表中選取 [新增專案參考]

  2. 在 [參考管理員] 對話框中,展開 [Projects] 節點,然後選取 StringLibrary旁的方塊。 將StringLibrary組件新增引用,可讓編譯器在編譯StringLibraryTest專案時找到StringLibrary方法

  3. 選擇 確定

新增和執行單元測試方法

當 Visual Studio 執行單元測試時,它會在以屬性標示的TestMethodAttribute類別中執行以屬性標TestClassAttribute示的每個方法。 當找到第一個失敗或方法中包含的所有測試成功時,測試方法就會結束。

最常見的測試會呼叫 Assert 類別的成員。 許多判斷提示方法至少包含兩個參數,其中一個是預期的測試結果,另一個是實際測試結果。 下表顯示一些 Assert 類別最常呼叫的方法:

Assert 方法 功能
Assert.AreEqual 驗證兩個值或物件是否相等。 如果值或物件不相等,斷言就會失敗。
Assert.AreSame 確認兩個物件變數參考相同的物件。 如果變數參考不同的對象,斷言將會失敗。
Assert.IsFalse 驗證條件為 false。 如果條件為 true,則斷言失敗。
Assert.IsNotNull 確認物件不是 null。 如果物件是 null,則斷言失敗。

如果在 MSTest 3.8 和更新版本中使用測試方法時,您也可以使用 Assert.ThrowsException(或 Assert.ThrowsAssert.ThrowsExactly)方法來指示預期會擲出的例外狀況類型。 如果未引發指定的例外狀況,測試就會失敗。

在測試 StringLibrary.StartsWithUpper 方法時,您想要提供許多以大寫字元開頭的字串。 您預期方法會在這些情況下傳回 true,因此您可以呼叫 Assert.IsTrue 方法。 同樣地,您希望提供許多以非大寫字母開頭的字串。 您預期方法會在這些情況下傳回 false,因此您可以呼叫 Assert.IsFalse 方法。

因為連結庫方法會處理字串,所以您也想要確定它已成功處理 空字串串 (String.Empty、沒有字元且其 Length 為 0 的有效字串,以及尚未初始化的 null 字串。 直接呼叫 StartsWithUpper 作為靜態方法,並傳遞單一 String 參數。 或呼叫StartsWithUpper作為指派給 string變數的null擴充方法。

定義三個方法,每個方法都會針對字串陣列中的每個元素呼叫一個 Assert 方法。 調用方法多載,以便讓您指定在測試失敗時要顯示的錯誤訊息。 訊息會識別造成失敗的字串。

若要建立測試方法:

  1. 在 [UnitTest1.csUnitTest1.vb 程式代碼] 視窗中,以下列程式代碼取代程序代碼:

    using UtilityLibraries;
    
    namespace StringLibraryTest;
    
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestStartsWithUpper()
        {
            // Tests that we expect to return true.
            string[] words = ["Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"];
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsTrue(result, $"Expected for '{word}': true; Actual: {result}");
            }
        }
    
        [TestMethod]
        public void TestDoesNotStartWithUpper()
        {
            // Tests that we expect to return false.
            string[] words = ["alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                              "1234", ".", ";", " "];
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsFalse(result, $"Expected for '{word}': false; Actual: {result}");
            }
        }
    
        [TestMethod]
        public void DirectCallWithNullOrEmpty()
        {
            // Tests that we expect to return false.
            string?[] words = [string.Empty, null];
            foreach (var word in words)
            {
                bool result = StringLibrary.StartsWithUpper(word);
                Assert.IsFalse(result, $"Expected for '{word ?? "<null>"}': false; Actual: {result}");
            }
        }
    }
    
    Imports Microsoft.VisualStudio.TestTools.UnitTesting
    Imports UtilityLibraries
    
    Namespace StringLibraryTest
        <TestClass>
        Public Class UnitTest1
            <TestMethod>
            Public Sub TestStartsWithUpper()
                ' Tests that we expect to return true.
                Dim words() As String = {"Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"}
                For Each word In words
                    Dim result As Boolean = word.StartsWithUpper()
                    Assert.IsTrue(result,
                           $"Expected for '{word}': true; Actual: {result}")
                Next
            End Sub
    
            <TestMethod>
            Public Sub TestDoesNotStartWithUpper()
                ' Tests that we expect to return false.
                Dim words() As String = {"alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " "}
                For Each word In words
                    Dim result As Boolean = word.StartsWithUpper()
                    Assert.IsFalse(result,
                           $"Expected for '{word}': false; Actual: {result}")
                Next
            End Sub
    
            <TestMethod>
            Public Sub DirectCallWithNullOrEmpty()
                ' Tests that we expect to return false.
                Dim words() As String = {String.Empty, Nothing}
                For Each word In words
                    Dim result As Boolean = StringLibrary.StartsWithUpper(word)
                    Assert.IsFalse(result,
                           $"Expected for '{If(word Is Nothing, "<null>", word)}': false; Actual: {result}")
                Next
            End Sub
        End Class
    End Namespace
    

    TestStartsWithUpper 方法中大寫字元的測試包括希臘大寫字母 "alpha" (U+0391) 和西里爾大寫字母 "EM" (U+041C)。 TestDoesNotStartWithUpper 方法中小寫字元的測試包括希臘小字母 Alpha (U+03B1) 和斯拉夫小字母 Ghe (U+0433)。

  2. 在功能表欄上,選取 [檔案]>[另存新檔為 UnitTest1.cs] 或 [檔案]>[另存另檔為 UnitTest1.vb] []。 在 [另存新檔] 對話框中,選擇 [儲存] 按鈕旁邊的箭頭,然後選擇 [使用編碼儲存]

    Visual Studio [另存新檔] 對話框

  3. 確認另存新檔 對話框中,選取 按鈕以儲存檔案。

  4. 在 [進階儲存選項] 對話框中,從 [編碼] 下拉式清單中選取 [Unicode (UTF-8 with signature) - 代碼頁 65001],然後選取 [確定]。

    Visual Studio [進階儲存選項] 對話框

    如果您無法將原始程式碼儲存為 UTF8 編碼檔案,Visual Studio 可能會將它儲存為 ASCII 檔案。 發生這種情況時,運行時間無法準確解碼 ASCII 範圍之外的 UTF8 字元,並且測試結果不正確。

  5. 在選單列上,選取 [[測試]>[執行所有測試]。 如果 [測試總管] 視窗 沒有打開,請選擇 [測試][測試總管]來開啟它。 這三個測試列在 [通過的測試] 區段中,而 [摘要] 區段會報告測試回合的結果。

    測試總管視窗顯示通過的測試

處理測試故障或失敗

如果您在進行測試驅動開發(TDD),先撰寫測試,在第一次執行它們時,測試會失敗。 然後將程式代碼新增至讓測試成功的應用程式。 在本教學課程中,您已在撰寫驗證的應用程式程式代碼之後建立測試,因此您沒看到測試失敗。 若要在預期測試失敗時驗證測試失敗,請將無效的值新增至測試輸入。

  1. 修改 words 方法中的 TestDoesNotStartWithUpper 陣列,以包含字串 “Error”。 您不需要儲存檔案,因為 Visual Studio 會在建置方案以執行測試時,自動儲存已開啟的檔案。

    string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " };
    
    Dim words() As String = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " }
    
    
  2. 從選單列選取 [測試>執行所有測試],以執行測試。 測試總管視窗 顯示兩個測試成功,一個失敗。

    具有失敗測試的[測試總管]視窗

  3. 選擇失敗的測試,TestDoesNotStartWith

    測試總管 視窗會顯示由斷言產生的訊息:「Assert.IsFalse 失敗。 預期 'Error': false;實際:沒錯。由於失敗,未測試「錯誤」之後陣列中的字串。

    [測試總管] 視窗,其中顯示 IsFalse 斷言失敗

  4. 拿掉您在步驟 1 中新增的字串 “Error”。 重新執行測試,並且測試通過了。

測試正式版本的函式庫

現在,在執行程式庫的偵錯組建時,測試都已通過,請針對程式庫的發行組建再次執行測試。 某些因素 (包括編譯器優化) 有時會在偵錯和發行組建之間產生不同的行為。

若要測試正式版本:

  1. 在 Visual Studio 工具列中,將組建組態從 Debug 變更為 Release

    Visual Studio 工具列,其中「發行組建」已被醒目提示

  2. [方案總管]中,按一下右鍵在 StringLibrary 專案上,然後從操作功能表中選取 [建置] 以重新編譯程式庫。

    在 StringLibrary 內容功能表中使用建置命令

  3. 從功能表列選擇 [測試]>[執行所有測試] 來執行單元測試。 測試通過了。

偵錯測試

如果您使用 Visual Studio 作為 IDE,您可以使用 教學課程:使用 Visual Studio 對 .NET 控制台應用程式進行偵錯 中顯示的相同過程,在您的單元測試專案中進行代碼偵錯。 不要啟動 ShowCase 應用程式專案,請以滑鼠右鍵點擊 StringLibraryTests 專案,然後從操作功能表中選取 [偵錯測試]

Visual Studio 會在附加調試程式時啟動測試專案。 執行會在您新增至測試專案或基礎程式庫程式碼的任何中斷點停止。

其他資源

後續步驟

在本教學課程中,您已經對類別函式庫進行單元測試。 將程式庫發佈至 NuGet 作為套件,讓其他人可以使用程式庫。 若要瞭解如何,請遵循 NuGet 教學課程:

使用 Visual Studio 建立及發佈 NuGet 套件

如果您將連結庫發佈為 NuGet 套件,其他人可以安裝並使用它。 若要瞭解如何,請遵循 NuGet 教學課程:

在 Visual Studio 中安裝和使用套件

函式庫不需要以套件的形式發行。 它可以與使用它的控制台應用程式搭配使用。 若要瞭解如何發佈主控台應用程式,請參閱本系列先前的教學課程:

使用 Visual Studio 發佈 .NET 控制台應用程式