快速入門:搭配測試總管進行以測試為導向的開發工作
我們建議您建立單元測試,以便讓您的程式碼在經歷許多漸進的開發步驟後仍然能夠正確運作。有數種架構都可以用來撰寫單元測試,包含由協力廠商所開發的架構。某些測試架構是專門讓您使用不同的語言或平台來進行測試。[測試總管] 提供單一介面,讓您使用任一種架構來進行單元測試。目前已有適用於最常用架構的配接器可供使用,而您也可以自己撰寫適用於其他架構的配接器。
[測試總管] 取代了舊版 Visual Studio 中的單元測試視窗。它的優點包括:
使用單一介面執行 .NET、Unmanaged、資料庫以及其他種類的測試。
使用您選擇的單元測試架構,例如 NUnit 或 MSTest 架構。
可在一個視窗中查看需要的所有資訊。
使用測試總管
若要使用測試總管來執行單元測試
建立使用您選擇的測試架構的單元測試。
例如,建立使用 MSTest 架構的測試:
建立測試專案。
在 [新增專案] 對話方塊中,展開 [Visual Basic]、[Visual C#] 或 [Visual C++],然後選擇 [測試]。
選取 [單元測試專案]。
將每個單元測試撰寫成方法。在每個測試方法的前面加上 [TestMethod] 屬性。
在功能表列上,選擇 [測試]、[執行單元測試]、[所有測試]。
接著就會建置方案並執行測試。
[測試總管] 會開啟並顯示測試結果的摘要。
**若要查看完整的測試清單:**請選擇任何分類中的 [全部顯示]。
若要返回摘要,請選擇 [首頁] 檢視。
**若要查看測試結果的詳細資料:**請在 [測試總管] 中選取測試,以便在詳細資料窗格中檢視詳細資料 (例如例外狀況訊息)。
**若要巡覽至測試的程式碼:**請在 [測試總管] 中按兩下測試,或在捷徑功能表上選擇 [開啟測試]。
**若要偵錯測試:**請開啟一個或多個測試的捷徑功能表,然後選擇 [偵測選取的測試]。
重要事項 |
---|
顯示的結果是最近執行的結果。有顏色的結果列只會顯示已執行的測試結果。例如,如果您執行許多測試,但是有些失敗了,接著只執行成功的測試,然後結果列就會全部顯示綠色。 |
注意事項 |
---|
如果未出現任何測試,請確定已安裝配接器將 [測試總管] 連接至您使用的測試架構。如需詳細資訊,請參閱搭配不同的測試架構來使用測試總管。 |
逐步解說:使用單元測試來開發方法
本逐步解說示範如何使用 Microsoft 單元測試架構以 C# 來開發受測方法。您可以輕鬆地將它改寫成其他語言,並使用其他測試架構 (例如 NUnit)。如需詳細資訊,請參閱使用不同的測試架構。
建立測試和方法
建立一個 Visual C# 類別庫專案。這個專案會包含所要提供的程式碼。在此範例中,它的名稱是 MyMath。
建立測試專案。
在 [新增專案] 對話方塊中,選擇 [Visual C#]、[測試],然後選擇 [單元測試專案]。
撰寫基本測試方法。驗證特定輸入所產生的結果:
[TestMethod] public void BasicRooterTest() { // Create an instance to test: Rooter rooter = new Rooter(); // Define a test input and output value: double expectedResult = 2.0; double input = expectedResult * expectedResult; // Run the method under test: double actualResult = rooter.SquareRoot(input); // Verify the result: Assert.AreEqual(expectedResult, actualResult, delta: expectedResult / 100); }
從測試產生方法。
將游標置於 Rooter 上,然後在捷徑功能表中選擇 [產生]、[新增類型]。
在 [產生新的類型] 對話方塊中,將 [專案] 設為類別庫專案。在這個範例中,是指 MyMath。
將游標置於 SquareRoot 上,然後在捷徑功能表中選擇 [產生]、[方法 Stub]。
執行單元測試。
在 [測試] 功能表列上,選擇 [執行單元測試]、[所有測試]。
接著就會建置並執行方案。
[測試總管] 會開啟並顯示測試結果。
此測試會出現在 [失敗的測試] 底下。
選取測試的名稱。
測試的詳細資料會顯示在 [測試總管] 的下半部。
選取 [堆疊追蹤] 底下的項目,以查看測試失敗的位置。
此時,您已建立要修改的測試和 stub,好讓測試能夠成功。
在每次變更後讓所有的測試都成功
在 MyMath\Rooter.cs 中,改善 SquareRoot 的程式碼:
public double SquareRoot(double input) { return input / 2; }
在 [測試總管] 中,選擇 [全部執行]。
接著就會建置程式碼並執行測試。
測試就會成功。
加入測試以擴充輸入的範圍
若要提高您對於程式碼在任何情況下都能運作的信心,您可以加入嘗試各種輸入值的測試。
提示 避免改變已經成功的現有測試,而改為加入新的測試。只有在使用者的需求改變時,才變更現有的測試。這個原則可協助您確保在擴充程式碼時不會失去現有的功能。
在您的測試類別中加入下面測試,該測試會嘗試某個範圍的輸入值:
[TestMethod] public void RooterValueRange() { // Create an instance to test: Rooter rooter = new Rooter(); // Try a range of values: for (double expectedResult = 1e-8; expectedResult < 1e+8; expectedResult = expectedResult * 3.2) { RooterOneValue(rooter, expectedResult); } } private void RooterOneValue(Rooter rooter, double expectedResult) { double input = expectedResult * expectedResult; double actualResult = rooter.SquareRoot(input); Assert.AreEqual(expectedResult, actualResult, delta: expectedResult / 1000); }
在 [測試總管] 中,選擇 [全部執行]。
新的測試失敗了,不過,第一個測試仍然成功。
若要找出失敗點,請選取失敗的測試,然後在 [測試總管] 的下半部選取 [堆疊追蹤] 的最上層項目。
檢查受測方法看看可能是哪裡出錯了。在 MyMath.Rooter 類別中,重寫程式碼:
public double SquareRoot(double input) { double result = input; double previousResult = -input; while (Math.Abs(previousResult - result) > result / 1000) { previousResult = result; result = result - (result * result - input) / (2 * result); } return result; }
在 [測試總管] 中,選擇 [全部執行]。
現在兩個測試都成功了。
加入例外狀況的測試
加入不正確輸入的測試:
[TestMethod] public void RooterTestNegativeInputx() { Rooter rooter = new Rooter(); try { rooter.SquareRoot(-10); } catch (ArgumentOutOfRangeException e) { return; } Assert.Fail(); }
在 [測試總管] 中,選擇 [全部執行]。
受測方法會產生迴圈現象,必須手動取消。
選擇 [取消]。
測試會在 10 秒之後停止。
修正方法程式碼:
public double SquareRoot(double input) { if (input <= 0.0) { throw new ArgumentOutOfRangeException(); } ...
在 [測試總管] 中,選擇 [全部執行]。
所有測試都成功。
重構但不變更測試
簡化程式碼,但不變更測試。
提示 「重構」(Refactoring) 是要讓程式碼的效能變得更好或讓程式碼更容易了解而做的變更。它不是要變更程式碼的行為,因此並不會變更測試。
我們建議您分開執行重構步驟與擴充功能的步驟。讓測試保持不變,您就會有信心沒有在重構時不小心引入了 Bug。
public class Rooter { public double SquareRoot(double input) { if (input <= 0.0) { throw new ArgumentOutOfRangeException(); } double result = input; double previousResult = -input; while (Math.Abs(previousResult - result) > result / 1000) { previousResult = result; result = (result + input / result) / 2; //was: result = result - (result * result - input) / (2*result); } return result; } }
選擇 [全部執行]。
所有測試仍然成功。