所謂單元測試(unit testing),就是對軟件中的最小單元進行檢查和驗證,其一般驗證對象是一個函數或者一個類。值得一提的是,雖然單元測試是開發者為了驗證一段代碼功能正確性而寫的一段代碼,但是我們寫一個單元測試的出發點并不是針對一段代碼或者一個方法,而是針對一個應用場景(scenario),即在某些條件下某個特定的函數的行為。
0. 單元測試的必要性
單元測試不但會使你的工作完成得更輕松,而且會令你的設計變得更好,甚至大大減少你花在調試上面的時間。
(1)單元測試能讓你確定自己的代碼功能和邏輯的正確性,還可以讓你增加對程序的信心,并且能夠及早發現程序中的不足。
(2)在寫好功能模塊之前、之中和之后考慮好單元測試怎么寫,不僅可以讓你更加清楚你寫的功能模塊的邏輯,還能及早地改進一些不當的設計。
(3)每完成一塊功能模塊就用單元測試進行驗證修改bug,比整個軟件寫完再驗證調試要容易得多。而且有了單元測試,在整體軟件出問題的時候,我們可以直接對懷疑的某模塊在單元測試中進行debug,這往往比調試整個系統要容易得多。
(4)幫助我們及早地發現問題。有的時候對A的修改可能會影響看起來毫不相關的B,如果沒有單元測試,A的修改checkin之后可能就會引發比較嚴重的問題。而如果在checkin之前能夠運行所有的單元測試的話,B的單元測試可能就會發現引入的問題,從而阻止此次不當修改的checkin。
我想,其實很多程序員都應該知道單元測試重要性的那些大道理,只是要改變它就像要戒掉拖延癥一樣。明明知道那樣不好并發誓下一次改進,卻一直沒有擺脫掉那些惡習。拜托,不要從明天或者從下一次開始了,就從現在開始吧!當你真正開始去寫單元測試并堅持寫,你會從中得到好處的,那時候你才會真正領悟到它的必要性。
1. 開始寫你的第一個單元測試吧
我們先來用VS2012中自帶的測試模塊來寫一個簡單的單元測試吧。
新建一個solution,并添加工程MyMathLib,在該工程中添加MyMathLib類,并書寫一個靜態的Largest()函數來找出一個整型列表中的最大值。然后添加一個TestLargest工程,如圖1所示,Add -> New Project 之后選擇Test -> Unit Test Project。新建好test工程之后,你會得到一個test模板,即一個帶有[TestClass] attribute標記的類和一個帶有[TestMethod] attribute標記的空方法public void TestMethod1()。
Figure 1. Add unit test project
現在我們的solution就具有了圖2中所示的目錄結構,打開剛添加的TestLargest工程下的references,我們可以看到它自動引用了Microsoft.VisualStudio.QuanlityTools.UnitTestFramework。
Figure 2. Projects in the solution
分別在MyMathLib和TestLargest添加代碼如下:
// MyMathLib.cs
namespace FirstUnitTest.MyMathLib
{
public static class MyMathLib
{
public static int Largest(List list)
{
int maxNum = Int32.MaxValue;
foreach (var num in list)
{
if (num > maxNum) maxNum = num;
}
return maxNum;
}
static void Main(string[] args)
{
}
}
}
// UnitTest1.cs
using FirstUnitTest.MyMathLib;
namespace FirstUnitTest.Test
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var list = new List() { 9, 8, 7 };
Assert.AreEqual(9, MyMathLib.MyMathLib.Largest(list));
}
}
}
寫好之后你會發現有編譯錯誤,cannot resolve MyMathLib.MyMathLib.Largest,所以我們在TestLargest工程里光添加using FirstUnitTest.MyMathLib;是不夠的,還需要在references中增加對MyMathLib工程的引用。這樣在TestMethod1()上單擊右鍵選擇Run Tests就可以在Test Explorer里看到單元測試的運行結果(如圖3所示)。
原文轉自:http://www.jianshu.com/p/7984955720e2