逐步解說:建立並執行 UWP 應用程式的單元測試

本文說明如何在 Visual Studio 中對通用 Windows 平台 (UWP) 應用程式進行單元測試。 Visual Studio 提供適用於 C#、Visual Basic 和 C++ 的 UWP 單元測試專案範本。 如需開發 UWP 應用程式的詳細資訊,請參閱 UWP 應用程式入門

本文將逐步解說在 UWP 應用程式中建立 C# 類別並進行單元測試的範例。 此範例會使用測試驅動開發來撰寫驗證特定行為的測試,然後撰寫通過測試的程式碼。

建立和執行單元測試專案

下列程序說明如何建立及執行 UWP 應用程式的單元測試專案。

建立 UWP 單元測試專案

  1. 在 Visual Studio 的 [開始] 視窗上,選擇 [建立新專案]

  2. 在 [建立新的專案] 頁面的搜尋方塊中,輸入「單元測試」。 範本清單會篩選至單元測試專案。

  3. 選取 C# 或 Visual Basic 的 [單元測試應用程式 (通用 Windows)] 範本,然後選取 [下一步]

    Screenshot that shows creating a new UWP unit test app in Visual Studio.

  4. 選擇性地變更專案或方案的名稱和位置,然後選取 [建立]

  5. 選擇性地變更目標和最低平台版本,然後選取 [確定]

Visual Studio 會建立測試專案,並在 Visual Studio [方案總管] 中開啟它。

Screenshot that shows the UWP unit test project in Solution Explorer.

  1. 在 Visual Studio 的 [開始] 視窗上,選擇 [建立新專案]

  2. 在 [建立新的專案] 頁面的搜尋方塊中,輸入「單元測試」。 範本清單會篩選至單元測試專案。

  3. 選取 C# 或 Visual Basic 的 [單元測試應用程式 (通用 Windows)] 範本,然後選取 [下一步]

    Screenshot that shows creating a new UWP unit test app in Visual Studio.

  4. 選擇性地變更專案或方案的名稱和位置,然後選取 [建立]

  5. 選擇性地變更目標和最低平台版本,然後選取 [確定]

Visual Studio 會建立測試專案,並在 Visual Studio [方案總管] 中開啟它。

Screenshot that shows the UWP unit test project in Solution Explorer.

編輯專案的應用程式資訊清單

  1. 在 [方案總管] 中,以滑鼠右鍵按一下 Package.appxmanifest 檔案並選取 [開啟]

  2. 在資訊清單設計工具中,選取 [功能] 索引標籤。

  3. 在 [功能] 清單中,選取程式碼和單元測試所需的功能。 例如,如果您的程式碼及其單元測試需要存取網際網路,請選取 [網際網路] 核取方塊。

只選取讓單元測試正常運作所需的功能。

Screenshot that shows a unit test manifest.

Screenshot that shows a unit test manifest.

新增程式碼以對 UWP 應用程式進行單元測試

在 Visual Studio 程式碼編輯器中,編輯單元測試程式碼檔案,以新增測試所需的判斷提示和邏輯。 如需範例,請參閱本文稍後的對 C# 類別進行單元測試

使用測試總管執行單元測試

使用 [測試總管] 建置方案與執行單元測試。

  1. 在 Visual Studio [測試] 功能表上,選取 [測試總管]。 [測試總管] 視窗隨即開啟。

  2. 在 [測試總管] 中,選取 [全部執行] 圖示。 您必須使用 [全部執行] 來探索 UWP 專案中的測試。

    Screenshot that shows Test Explorer Run all icon.

方案會建置執行並進行單元測試。 測試執行之後,測試會出現在 [測試總管] 測試清單中,其中包含結果和持續時間的相關資訊。

Screenshot that shows the Test Explorer with completed test information.

此外,您也可以在 [測試總管] 中選取個別測試,並以滑鼠右鍵按一下 [執行] 或 [偵錯] 測試,或 [前往測試] 以開啟測試程式碼。 從頂端功能表中,您可以將測試分組、將測試新增至播放清單,或開啟測試選項。

Screenshot that shows a Test Explorer context menu.

使用 [測試總管] 建置方案與執行單元測試。

  1. 在 Visual Studio [測試] 功能表上,選取 [測試總管]。 [測試總管] 視窗隨即開啟。

  2. 在 [測試總管] 中,選取 [全部執行] 圖示。 您必須使用 [全部執行] 來探索 UWP 專案中的測試。

    Screenshot that shows Test Explorer Run all icon.

方案會建置執行並進行單元測試。 測試執行之後,測試會出現在 [測試總管] 測試清單中,其中包含結果和持續時間的相關資訊。

Screenshot that shows the Test Explorer with completed test information.

此外,您也可以在 [測試總管] 中選取個別測試,並以滑鼠右鍵按一下 [執行] 或 [偵錯] 測試,或 [前往測試] 以開啟測試程式碼。 從頂端功能表中,您可以將測試分組、將測試新增至播放清單,或開啟測試選項

Screenshot that shows a Test Explorer context menu.

對 C# 類別進行單元測試

一組穩定而良好的單元測試,可讓您確信並未在變更程式碼時引入錯誤。 下列範例會逐步解說如何在 UWP 應用程式中建立 C# 類別的單元測試。 此範例會使用測試驅動開發來撰寫驗證特定行為的測試,然後撰寫通過測試的程式碼。

Maths 程式碼專案的範例中,Rooter 類別會實作函式,以計算數字的預估平方根。 RooterTests 專案會對 Rooter 類別進行單元測試。

建立方案和專案

建立 UWP 應用程式專案:

  1. 在 Visual Studio 的 [檔案] 功能表上,選取 [新增專案]
  2. 在 [建立新專案] 頁面上,於 [搜尋] 方塊中輸入空白應用程式,然後選取 C# [空白應用程式 (通用 Windows)] 專案範本。
  3. 在 [設定新專案] 頁面上,將專案命名為 Maths,然後選取 [建立]
  4. 選擇性地變更目標和最低平台版本,然後選取 [確定]。 Visual Studio 隨即建立專案,並在 [方案總管] 中開啟該專案。

建立單元測試專案:

  1. 在 [方案總管] 中,以滑鼠右鍵按一下 Maths 方案,然後選擇 [新增]>[新增專案]
  2. 在 [新增專案] 頁面上,於 [搜尋] 方塊中輸入單元測試,然後選取 C# [單元測試應用程式 (通用 Windows)] 專案範本。
  3. 將測試專案命名為 RooterTests,然後選取 [建立]
  4. 選擇性地變更目標和最低平台版本,然後選取 [確定]RooterTests 專案會出現在 [方案總管] 中的 Maths 方案底下。

驗證測試總管中執行的測試

Assert 類別提供數個靜態方法,可讓您在測試方法中用來驗證結果。

  1. 在 [方案總管] 中,選取 RooterTests 專案中的 UnitTest1.cs 檔案。

  2. 將下列程式碼插入 TestMethod1

    [TestMethod]
    public void TestMethod1()
    {
        Assert.AreEqual(0, 0);
    }
    
  3. 在 [測試總管] 中,選取 [執行所有測試]

  4. 測試專案會建置並執行,而測試會出現在 [通過的測試] 底下。 右側的 [群組摘要] 窗格提供測試的詳細資料。

將類別新增至應用程式專案

  1. 在 [方案總管] 中,於 Maths 專案上按一下滑鼠右鍵,然後選取 [新增]>[類別]

  2. 將類別檔案命名為 Rooter.cs,然後選取 [新增]

  3. 在程式碼編輯器中,將下列程式碼新增至 Rooter.cs 檔案中的 Rooter 類別:

    public Rooter()
    {
    }
    
    // estimate the square root of a number
    public double SquareRoot(double x)
    {
        return 0.0;
    }
    

    Rooter 類別會宣告建構函式和 SquareRoot 評估工具方法。 SquareRoot 方法是測試基本測試設定的最小實作。

  4. internal 關鍵字變更為 Rooter 類別宣告中的 public,讓測試程式碼可以存取它。

    public class Rooter
    
  1. 在 [方案總管] 中,於 Maths 專案上按一下滑鼠右鍵,然後選取 [新增]>[類別]

  2. 將類別檔案命名為 Rooter.cs,然後選取 [新增]

  3. 在程式碼編輯器中,將下列程式碼新增至 Rooter.cs 檔案中的 Rooter 類別:

    public Rooter()
    {
    }
    
    // estimate the square root of a number
    public double SquareRoot(double x)
    {
        return 0.0;
    }
    

    Rooter 類別會宣告建構函式和 SquareRoot 評估工具方法。 SquareRoot 方法是測試基本測試設定的最小實作。

  4. public 關鍵字新增至 Rooter 類別宣告,讓測試程式碼可以存取它。

    public class Rooter
    

將測試專案的參考新增至應用程式專案

  1. 在 [方案總管] 中 ,以滑鼠右鍵按一下 RooterTests 專案,然後選取 [新增]>[參考]

  2. 在 [參考管理員 - RooterTests] 對話方塊中,展開 [專案],然後選取 Maths 專案。

    Screenshot that shows adding a reference to the Maths project.

  3. 選取 [確定]。

  4. using Microsoft.VisualStudio.TestTools.UnitTesting; 行之後,將下列 using 陳述式新增至 UnitTest.cs

    using Maths;
    
  1. 在 [方案總管] 中 ,以滑鼠右鍵按一下 RooterTests 專案,然後選取 [新增]>[參考]

  2. 在 [參考管理員 - RooterTests] 對話方塊中,展開 [專案],然後選取 Maths 專案。

    Screenshot that shows adding a reference to the Maths project.

  3. 選取 [確定]。

  4. 在行之後 using Microsoft.VisualStudio.TestTools.UnitTesting;,將下列 using 陳述式新增至 UnitTest.cs

    using Maths;
    

新增使用應用程式函式的測試

  1. 將下列測試方法新增至 UnitTest.cs

    [TestMethod]
    public void BasicTest()
    {
        Maths.Rooter rooter = new Rooter();
        double expected = 0.0;
        double actual = rooter.SquareRoot(expected * expected);
        double tolerance = .001;
        Assert.AreEqual(expected, actual, tolerance);
    }
    

    新的測試會出現在 [方案總管] 和 [測試總管] 的 [未執行測試] 節點中。

  2. 若要避免「承載包含兩個或多個具有相同目的地路徑的檔案」錯誤,請在 [方案總管] 中展開 Maths 專案下的 [屬性] 節點,並刪除 Default.rd.xml 檔案。

  3. 儲存所有檔案。

執行測試

在 [測試總管] 中,選取 [執行所有測試] 圖示。 接著方案就會建置並執行測試然後通過。

Screenshot that shows Basic Test passed in Test Explorer

在 [測試總管] 中,選取 [執行所有測試] 圖示。 接著方案就會建置並執行測試然後通過。

Screenshot that shows Basic Test passed in Test Explorer

如果您在執行測試時收到「重複的實體」錯誤,請從測試專案中刪除執行階段指示詞檔案 Properties\Default.rd.xml,然後重新嘗試。

您已設定測試和應用程式專案,並確認您可以執行可在應用程式專案中呼叫函式的測試。 現在您可以撰寫實際的測試和程式碼。

新增測試並讓測試通過

最好不要變更已通過的測試。 請改為新增測試。 藉由一次新增一個測試來開發程式碼,並確定所有測試都會在每個反覆項目之後通過。

  1. 將名為 RangeTest 的新測試新增至 UnitTest.cs

    [TestMethod]
    public void RangeTest()
    {
        Rooter rooter = new Rooter();
        for (double v = 1e-6; v < 1e6; v = v * 3.2)
        {
            double expected = v;
            double actual = rooter.SquareRoot(v*v);
            double tolerance = expected/1000;
            Assert.AreEqual(expected, actual, tolerance);
        }
    }
    
  2. 執行 RangeTest 測試,並確認它失敗。

    Screenshot that shows the RangeTest fails in Test Explorer.

    提示

    在測試驅動開發中,您會在撰寫測試之後立即執行測試。 此做法有助於避免撰寫永遠不會失敗的測試這種易犯的錯誤。

  3. 修正您的應用程式程式碼,讓新的測試通過。 在 Rooter.cs 中,變更 SquareRoot 函式,如下所示:

    public double SquareRoot(double x)
    {
        double estimate = x;
        double diff = x;
        while (diff > estimate / 1000)
        {
            double previousEstimate = estimate;
            estimate = estimate - (estimate * estimate - x) / (2 * estimate);
            diff = Math.Abs(previousEstimate - estimate);
        }
        return estimate;
    }
    
  4. 在 [測試總管] 中,選取 [執行所有測試] 圖示。 現在三項測試都會成功。

  1. 將名為 RangeTest 的新測試新增至 UnitTest.cs

    [TestMethod]
    public void RangeTest()
    {
        Rooter rooter = new Rooter();
        for (double v = 1e-6; v < 1e6; v = v * 3.2)
        {
            double expected = v;
            double actual = rooter.SquareRoot(v*v);
            double tolerance = expected/1000;
            Assert.AreEqual(expected, actual, tolerance);
        }
    }
    
  2. 執行 RangeTest 測試,並確認它失敗。

    Screenshot that shows the RangeTest fails in Test Explorer.

    提示

    在測試驅動開發中,您會在撰寫測試之後立即執行測試。 此做法有助於避免撰寫永遠不會失敗的測試這種易犯的錯誤。

  3. 修正您的應用程式程式碼,讓新的測試通過。 在 Rooter.cs 中,變更 SquareRoot 函式,如下所示:

    public double SquareRoot(double x)
    {
        double estimate = x;
        double diff = x;
        while (diff > estimate / 1000)
        {
            double previousEstimate = estimate;
            estimate = estimate - (estimate * estimate - x) / (2 * estimate);
            diff = Math.Abs(previousEstimate - estimate);
        }
        return estimate;
    }
    
  4. 在 [測試總管] 中,選取 [執行所有測試] 圖示。 現在三項測試都會成功。

重構程式碼

在本節中,您會重構應用程式和測試程式碼,然後重新執行測試,以確定程式碼仍然會通過。

簡化平方根估計

  1. Rooter.cs 中,藉由變更下列這一行來簡化 SquareRoot 函式中的中央計算:

    estimate = estimate - (estimate * estimate - x) / (2 * estimate);

    目標

    estimate = (estimate + x/estimate) / 2.0;

  2. 執行所有測試,以確定您並未引入迴歸。 測試應該會通過。

移除重複的測試程式碼

RangeTest 方法會對傳遞至 tolerance 方法之 Assert 變數的分母採用硬式編碼。 如果您打算新增更多使用相同容錯計算的測試,請在數個位置使用硬式編碼值,讓程式碼更難維護。 相反地,您可以將私人協助程式方法新增至 UnitTest1 類別以計算容錯值,然後從 RangeTest 呼叫該方法。

若要新增協助程式方法,請在 UnitTest.cs 中:

  1. 將下列方法新增至 UnitTest1班級:

    private double ToleranceHelper(double expected)
    {
        return expected / 1000;
    }
    
  2. RangeTest 中,變更下列這一行:

    double tolerance = expected/1000;

    目標

    double tolerance = ToleranceHelper(expected);

  3. 執行 RangeTest 測試以確定它仍然會通過。

提示

如果您將協助程式方法新增至測試類別,且您不希望協助程式方法出現在 [測試總管] 的清單中,請勿將 TestMethodAttribute 屬性新增至該方法。

下一步