Nunit工具做C#的單元測試
學習心得
編寫人:羅旭成
時間:2013年9月2日星期一
1.開發人員如何做單元測試
單元測試是針對最小的可測試軟件元素(單元)的,它所測試的內容包括單元的內部結構(如邏輯和數據流)以及單元的功能和可觀測的行為。使用白盒測試方法測試單元的內部結構,使用黑盒測試方法測試單元的功能和可觀測的行為。
由於開發方式的不同,單元測試一般划分方法如下:
1. 面向對象的軟件開發:以Class(類)作為測試的最小單元。以方法的內部結構作為測試的重點。
2. 結構化的軟件開發:以模塊(函數、過程)作為測試的最小單元。
a.代碼的可讀性
開發人員在寫代碼的時候都有自己的習慣,比如在寫一個新的類的時候,類的名稱有的用英語命名,有的用漢語拼音命名。而對於注釋而言,有的存在一部分,有的從頭到尾根本沒有注釋(這樣的代碼讓開發人員過半年自己再看,他自己也可能不知道這段代碼實現的是什么功能)那么是否有一段可用代碼編寫規范在執行,開發人員是否都按規范來進行開發,一段開發人員自己都看不明白的代碼,該如何進行單元測試?特別是對公用的方法要進行注釋,這樣會減少單元測試的時間。可見規范化的代碼編寫是進行單元測試必不可少的一部分。
b.設計單元測試
在進行單元測試之前需要弄清楚被測試代碼實現的功能和相應的邏輯關系;同時還要考慮到測試的輸入內容。也就是說,測試用例的設計。用例的設計要保證面面俱到,是否覆蓋了每一條路徑。而如何做到面面俱到這就需要開發人員對每個函數進行詳細的分析,將分析和討論的結果歸入相關的測試庫中。初期工作的進度慢並不要緊,只要能做得很詳細對於以后的測試還是有很大的幫助。或許以后的測試中,只要直接調用原來寫過的測試類庫,修改部分簡單的語句就可以實現新模塊的單元測試了。
2.Nunit的安裝
Nunit是一款開源的C#單元測試工具,下載地址為:http://www.nunit.org/index.php?p=download ,
目前最高版本為:2.6.2。安裝文件為: ,
例子文件: ,下載安裝。
VS2010 NUnit 整合插件 Visual Nunit 2010下載:http://visualstudiogallery.msdn.microsoft.com/c8164c71-0836-4471-80ce-633383031099 , 下載安裝完畢就能在 VS2010 的 view(視圖)->Other Windows(其他窗口)中看到 Visual Nunit了(或使用快捷鍵Ctrl + F7),打開該視圖,將之拖到合適的位置。如下圖(2.1.1):
圖(2.1.1)
3.測試樣例程序
3.1、新建測試項目UnitTestApp(示例為簡單的控制台應用程序),引入nunit.framework類庫(默認安裝后文件所在路徑:C:\Program Files \NUnit 2.6\bin\framework\nunit.framewor.dll)
3.2、添加Calculator類,實現一個簡單加法和獲取單例方法
namespace UnitTestApp
{
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
private static readonly object objSync = new object();
private static Calculator instance = null;
public static Calculator GetInstance()
{
if (instance == null)
{
lock (objSync)
{
if (instance == null)
{
instance = new Calculator();
}
}
}
return instance;
}
}
}
3.3、新增NUnitTest類進行單元測試
using NUnit.Framework;
namespace UnitTestApp
{
[TestFixture]
public class NUnitTest
{
[Test]
public void AddTest()
{
var calc = new Calculator();
var result = calc.Add(1, 1);
Assert.AreEqual(2, result);//判斷是否相等
}
[Test]
public void AddTestFailure()
{
var calc = new Calculator();
var result = calc.Add(1, 1);
Assert.AreEqual(10, result); //判斷是否相等
}
[Test]
public void SingtonTest1()
{
var calc = Calculator.GetInstance();
Assert.IsNull(calc); //判斷是否空值
}
[Test]
public void SingtonTest2()
{
var calc1 = Calculator.GetInstance();
var calc2 = Calculator.GetInstance();
Assert.IsTrue(object.Equals(calc1, calc2)); //對象比較
}
}
}
編譯控制台項目,點擊Visual Nunit 插件的“Run”按鈕,然后一切清靜了。
注:在上面的代碼中引用 NUnit.Framework,使用TestFixture標注這是用於測試的類,在其中使用Test表示具體的測試用例。可以看到單元測試中最重要的是斷言,其他完全交給框架自動化。測試結果可以通過插件及時看到:
測試例子程序:
4.測試代碼必須做以下幾件事情
1) 准備測試所需的條件
2) 調用要測試的方法
3) 驗證被測方法的行為和期望的行為是否一致
4) 完成后清理各種資源
5.使用NUnit框架,需要做這些工作
1) 使用using聲明引用必要的NUnit類(並添加一個指向NUnitDll的引用)
2) 定義一個測試類,必須是Public的、包換一個public的沒有參數的構造函數,並且在類定義上加上[TestFixture]attribute標記。(表明是測試類)
3) 在測試類中包含用[Test]attribute標記的方法。(表明是測試方法)
6.Nunit斷言類介紹
Nunit一共有四個斷言類,分別是Assert、StringAssert、FileAssert和DirectoryAssert,它們都在NUnit.Framework命名空間,其中Assert是常用,也是我們最熟悉的,而另外三個斷言類,顧名思義,分別對應於字符串的斷言、文件的斷言和目錄的斷言,理論上,僅Assert類就可以完成所有條件的判斷,然而,如果合理的運用后面的三個斷言,將使代碼更加簡潔、美觀,也更加便於理解和維護。
一:Assert類
對於我們通常的單元測試代碼,Assert類中的靜態方法就可以完成,其中大家最熟悉的應該是Assert. AreEqual()方法,其實,除了AreEqual,NUnit還提供了眾多的比較方式,滿足不同的代碼要求。
1:相等/不相等判斷
AreEqual:判斷兩個值相等
AreNotEqual:判斷兩個值不相等
示例:
Int a=1 Assert.AreEqual(a,1);//通過判斷 Assert.AreEqual(a,2);//不能通過判斷
注意,除了AreEqual/ AreNotEqual,下面幾乎所有的方法都支持多態(多種數據類型),以及多參數,除了經常使用的Assert .AreEqual(int a,int b),還有一種典型的參數形式: Assert.AreEqual(int a,int b,string message);
或者 Assert.XXX(int a,int b,string message);
其中第三個參數是條件不通過時輸出的信息,以便於錯誤的定位
對於double和decimal類型,這兩個方法還支持比較時的浮點誤差
例如以下代碼:
double a = 1.1; double b = 1.11; double c = 0.1; Assert.AreEqual(a, b, c);//通過判斷 c=0.01; Assert.AreEqual(a, b, c);//不能通過判斷
2:類的判斷
AreSame:判斷兩個對象相等
AreNotSame:判斷兩個對象不相等
Contains:判斷是否是否某對象
示例:
List<string> list = new List<string>(); list.Add("a"); list.Add("b"); Assert.Contains("a", list); //通過判斷 Assert.Contains("aa", list); //不能通過判斷
3:條件判斷
IsTrue/True:判斷條件為真
IsFalse/False:判斷條件為假
IsNull/Null:判斷是否為空
IsNotNull/NotNull:判斷不為空
IsNaN:判斷數值是Nan
IsEmpty/IsNotEmpty:判斷字符串是否為空/不為空
IsEmpty/IsNotEmpty:判斷集合是否為空/不為空
其中True,IsTrue類似的都有兩個版本,其中IsTrue是用來兼容以前的版本的。
示例:
int a=100; Assert.IsTrue(a==100);//通過判斷 Assert.True(a==100);//通過判斷
4:比較判斷
Greater:大於
GreaterOrEqual:大於等於
Less:小於
LessOrEqual:小於大於
示例:
int a = 100; Assert.Greater(a, 99); Assert.GreaterOrEqual(a, 100);
5:類型判斷
IsInstanceOfType/IsNotInstanceOfType:是/不是某個類的實例(從2.5之后支持泛型)
public class Person { public string name {set;get;} } Person p = new Person(); p.name = "a"; Assert.IsInstanceOf(typeof(Person), p);//通過判斷 Assert.IsInstanceOf(typeof(System.String), p);//不能通過判斷
6:異常判斷
Throws:應該拋出某類型的異常
DoesNotThrow:不應該拋出某類型的異常
7:其它常用的方法
Pass:強行讓測試通過
Fail:強行讓測試失敗
Ignore:忽略該測試方法
Inconclusive:未驗證該測試
Assert.Pass();
Assert.Pass(string message );
Assert.Pass(string message, object[] parms );
Assert.Fail();
Assert.Fail(string message );
Assert.Fail(string message, object[] parms );
Assert.Ignore();
Assert.Ignore(string message );
Assert.Ignore(string message, object[] parms );
Assert.Inconclusive();
Assert.Inconclusive(string message );
Assert.Inconclusive(string message, object[] parms );
這些方法讓我們能直接控制測試的進程,其中Assert.Pass 讓你直接通過測試來結束這次的測試:這會導致一個異常產生,是高效的讓測試返回的方法。除此之外,你也可以提供一個消息,讓我們可以直觀看出原因。
Assert.Fail 可以讓測試失敗為結果來結束本次測試。
Assert.Ignore 讓我們有能力動態的忽略某個測試或條件。它可以在test,setup,fixture setup方法中調用。建議只在單獨的條件內調用,因為Nunit的分類機制提供更廣泛的如包含、排除等,你可以更簡單的選擇讓測試運行在不同的場合或者程序集。
Assert.Inconclusive 的作用是指出現有條件下,測試不能完成:因為它不能證明斷言是成功或失敗。
這幾個方法一樣,即使把它放到一個獨立的方法中,然后再調用這個方法,它仍然會被激發來結束測試。
二:StringAssert類
StringAssert用於String類型的斷言判斷:
StringAssert.Contains:是否包含子串
StringAssert.StartsWith:是否以某子串開頭
StringAssert.EndsWith:是否以某子串結尾
StringAssert.AreEqualIgnoringCase:兩個字符串是否在不區分大小寫時相等
StringAssert.IsMatch:是否匹配,(使用正則表達式進行字符串比較)
示例:
string s1 = "abc"; StringAssert.Contains("b", s1); StringAssert.StartsWith("a", s1); StringAssert.EndsWith("c", s1); string s2 = "aBc"; StringAssert.AreEqualIgnoringCase(s1, s2); StringAssert.IsMatch("[a|book]", "123");
三:CollectionAssert類
AllItemsAreInstancesOfType:集合中的各項是否是某某類型的實例
AllItemsAreNotNull:集合中的各項均不為空
AllItemsAreUnique:集合中的各項唯一
AreEqual:兩個集合相等
AreEquivalent:兩個集合相當
AreNotEqual:兩個集合不相等
AreNotEquivalent:兩個集合不相當
DoesNotContain:集合中不包含某對象
IsSubsetOf:一個集合是另外一個集合的子集
IsNotSubsetOf:一個集合不是另外一個集合的子集
IsEmpty:集合為空
IsNotEmpty:集合不為空
IsOrdered:集合的各項已經排序
示例:
List<int> a = new List<int>(); List<int> b = new List<int>(); CollectionAssert.IsEmpty(a); for (int i = 1; i <= 10; i++) { a.Add(i); b.Add(i); } CollectionAssert.AreEqual(a, b); CollectionAssert.IsOrdered(a); b.Remove(1); CollectionAssert.IsSubsetOf(b, a); CollectionAssert.AreEqual(a, b);
CollectionAssert類提供的這些方法主要用於檢查集合或者集合內容或者來比較兩個集合。
AreEqual 的重載方法要求兩個集合的對應元素要相等,而 AreEquivalent 要求兩個集合的內容相等,而不要求順序。兩者元素的比較都應用默認的相等比較。
四:FileAssert類
FileAssert用於文件的比較判斷:
AreEqual:判斷兩個值相等
AreNotEqual:判斷兩個值不相等
文件的比較,用來比較兩個文件,可以Streams,FileInfos 或者路徑的形式。
FileAssert.AreEqual( Stream expected, Stream actual );
FileAssert.AreNotEqual( Stream expected, Stream actual );
五:DirectoryAssert類
這個類提供的方法讓我們可以對系統的文件目錄進行斷言,可以以DirectoryInfos 或者路徑 的形式。
AreEqual:判斷兩個值相等
AreNotEqual:判斷兩個值不相等
用來比較兩個目錄是否相等:相同的全名,屬性Attributes, 創建時間CreationTime 和最后訪問時間LastAccessTime. 兩個包含相等文件的不同目錄是不會被認為相同的。
DirectoryAssert.AreEqual( DirectoryInfo expected, DirectoryInfo actual );
DirectoryAssert.AreNotEqual( DirectoryInfo expected, DirectoryInfo actual );
IsEmpty:集合為空
IsNotEmpty:集合不為空
這些被用來測試目錄是否為空。
DirectoryAssert.IsEmpty(DirectoryInfo directory);
DirectoryAssert.IsNotEmpty(DirectoryInfo directory);
IsWithin:是子目錄
IsNotWithin:不是子目錄
DirectoryAssert.IsWithin(DirectoryInfo expected,DirectoryInfo actual);
DirectoryAssert.IsNotWithin(DirectoryInfo expected,DirectoryInfo actual);
這些方法用來測試第二個目錄是不是第一個目錄的子(孫子等)目錄。
7.Nunit屬性介紹
Nunit屬性可分為四大類,分別是控制類、數值類、平台類和其他類。
一:控制類
這些Attribute控制測試類或者測試方法,而且成對出現,功能基本相比,了解一個就自然了解另外一個。
[TestFixture]/[Explicit]:聲明一個類是測試類/聲明一個類只有在UI界面被選中時才執行
[TestFixtureSetup]/[TestFixtureTearDown]:在測試開始前/結束后要執行的操作,一個TestFixture只能有一個TestFixtureSetup或TestFixtureTearDown。
[Test]/[Ignore]:是測試方法/忽略掉,測試時不執行
[Setup]/[TearDown]:每個測試方法在執行前/結束后要執行的操作
二:數值類
數值類Attribue是NUnit的一大亮點,善於使用這些Attribue,將使測試方法變得清晰、簡潔、可讀性強、可擴展性強,有利於進行數據驅動下的測試。
為了說明下面的例子,使用下面的方法,也就是打印輸出輸入值及其數據類型,這樣便於把執行的結果通過打印的方式在NUnit中輸出
Console.WriteLine(t + ", its type:" + typeof(T));
[Values]:以參數的形式傳入一組值,NUnit會把這組值分解成相應數量的子測試。
例如下面的代碼,分別在[Values]中傳入三組共8個值,在執行時便一共會分解成8個子測試方法,例如
TestPrintInt([Values(1, 2, 3)] int x)會被分解為 TestPrintInt(1) TestPrintInt(2) TestPrintInt(3)三組
如下圖,當選中ValueDemo這個節點,然后點擊Run按鈕后,會看到一共測試了8個測試用例。
[ValueSource]:以數據源(Object類型)作為參數,如下圖,左邊是源程序,右邊是編譯后生成的子測試
[Combinatorial]:兩組測試數據進行組合,下面的代碼會生成12個子測試,如圖
[Sequential]:和上面[Combinatorial]的類似,不同之處見下圖
[Range]:生成某個數據范圍內的子測試,如
TestPrintColsole([Range(0.2, 0.6, 0.2)] double d):生成0.2,0.4,0.6三個子測試用例 TestPrintColsole([Values(1, 2, 3, 4, 5, 6)] int x, [Range(0.2, 0.6, 0.2)] double d):兩個Attribuee結合,共生成18個子測試用例
[Random]:在某個范圍內隨機生成測試用例,
TestPrintColsole([Random(-1.0, 1.0, 5)] double d):-1到1之間生成5個測試用例 TestPrintColsole([Values(1, 2, 3, 4, 5, 6)] int x, [Random(-1.0, 1.0, 5)] double d) :共生成30個子測試用例
三:平台類
[Culture]:當Culture滿足某條件下,才執行測試,如:
[Culture("fr-FR")]:僅當在法文Culture時,執行測試 [Culture(Exclude = "en,de")]:非英文和德文Culture時,才執行測試
[Platform]:當Platform滿足某條件下,才執行測試,如:
[Platform("NET-4.0")]:僅當framework版本是4.0時,才執行測試
下面是NUnit官網聲稱的,其支持的平台類型:
Win |
Win32 |
Win32S |
Windows |
Win32NT |
WinCE |
Win95 |
Win98 |
WinMe |
NT3 |
NT4 |
NT5 |
NT6 |
Win2K |
WinXP |
Win2003Server |
Vista |
Win2008Server |
Win2008ServerR2 |
Windows7 |
Unix |
Linux |
Net |
Net-1.0 |
Net-1.1 |
Net-2.0 |
Net-3.0 |
Net-3.5 |
Net-4.0 |
NetCF |
SSCLI |
Rotor |
Mono |
Mono-1.0 |
Mono-2.0 |
Mono-3.0 |
Mono-3.5 |
|
|
|
四:其它類
[Category]:將測試方法分組,NUnit會取出所有的組名,列在Categories中,點擊它可以看到。這提供了另外一種測試用例的運行方法,用戶可以在些選擇某一類的用例進行測試,而不是只能以點擊分單位
[ExpectedException]:運行時拋出的異常才能預期的行為。
如果沒有這個Attribute,要測試某些異常時,只能使用Try Catch的方式,而下面的代碼則更為簡潔:
[Test] [ExpectedException(typeof(System.DivideByZeroException))]//發生DivideByZeroException時,測試通過 public void Test1() { int a = 0; int b = 1 / a; PrintConsole<object>.Print(b); } [Test] [ExpectedException( "System.DivideByZeroException")]//發生DivideByZeroException時,測試通過
public void Test2() { int a = 0; int b = 1 / a; PrintConsole<object>.Print(b); }
[Maxtime]/ [Timeout]: 測試用例的最大執行時間,前者超時時不取消測試,而后者會強行中斷,用法如下
[Test, Maxtime(2000)] [Test, Timeout(2000)]
[Repeat]: 重復執行多少次,用法如下
[Test, Repeat(100)]
[RequiresMTA]/ [RequiresSTA]/ [RequiresThread]:測試用例必須的在多線程、單線程、獨立的線程狀態下運行。
8.對比MS Test與NUnit Test框架
一、簡介
MS Test框架是Visual Studio自帶的測試框架,可以通過新建一個Unit Test Project工程,也可以建一個Class Libary,然后添加對Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll的引用。然后就是創建測試用例,進行測試即可。
NUnit Test框架是一個xUnit家族種的第4個主打產品,完全由C#語言來編寫,支持所有的.Net語言。
使用NUnit框架,我們需要下載安裝包,安裝后使用獨立客戶端進行使用。使用方法與MS Test類似,新建一個Class Libary,然后添加對nunit.framework.dll的引用,最后創建測試用例,在客戶端中進行測試。
二、特性標簽對比
所有的測試框架都共享相同的核心特性:Test Declaration, Test Execution, and Assertions.
在.Net中一般使用特性標簽來添加額外的信息,下面就是MS Test和NUnit在特性標簽上不同的地方。
MS Test Attribute |
NUnit Attribute |
用途 |
[TestClass] |
[TestFixture] |
定義一個測試類,里面可以包含很多測試函數和初始化、銷毀函數(以下所有標簽和其他斷言)。 |
[TestMethod] |
[Test] |
定義一個獨立的測試函數。 |
[ClassInitialize] |
[TestFixtureSetUp] |
定義一個測試類初始化函數,每當運行測試類中的一個或多個測試函數時,這個函數將會在測試函數被調用前被調用一次(在第一個測試函數運行前會被調用)。 |
[ClassCleanup] |
[TestFixtureTearDown] |
定義一個測試類銷毀函數,每當測試類中的選中的測試函數全部運行結束后運行(在最后一個測試函數運行結束后運行)。 |
[TestInitialize] |
[SetUp] |
定義測試函數初始化函數,每個測試函數運行前都會被調用一次。 |
[TestCleanup] |
[TearDown] |
定義測試函數銷毀函數,每個測試函數執行完后都會被調用一次。 |
[AssemblyInitialize] |
-- |
定義測試Assembly初始化函數,每當這個Assembly中的有測試函數被運行前,會被調用一次(在Assembly中第一個測試函數運行前會被調用)。 |
[AssemblyCleanup] |
-- |
定義測試Assembly銷毀函數,當Assembly中所有測試函數運行結束后,運行一次。(在Assembly中所有測試函數運行結束后被調用) |
[DescriptionAttribute] |
[Category] |
定義標識分組。 |
三、同時支持NUnit和MSTest
通過上面的介紹,我們可以看到這兩個框架只是標簽的寫法不一樣,它們的具體功能都是一樣的。
所以可以通過宏判斷來同時支持這兩個框架。
1、添加兩種框架的DLL
MSTest: Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
NUnit : nunit.framework.dll
2、在測試前添加以下代碼:
#if !NUNIT
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Category = Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute;
#else
using NUnit.Framework;
using TestClass = NUnit.Framework.TestFixtureAttribute;
using TestMethod = NUnit.Framework.TestAttribute;
using TestInitialize = NUnit.Framework.SetUpAttribute;
using TestCleanup = NUnit.Framework.TearDownAttribute;
using TestContext = System.Object;
using ClassCleanup = NUnit.Framework.TestFixtureTearDownAttribute;
using ClassInitialize = NUnit.Framework.TestFixtureSetUpAttribute;
#endif
四、斷言對比
同上,大部分都是一樣的,有些地方不太一樣而已。
MS Test Assert |
NUnit Assert |
用途 |
AreEqual |
|
驗證值相等 |
AreNotEqual |
|
驗證值不相等 |
AreSame |
|
驗證引用相等 |
AreNotSame |
|
驗證引用不相等 |
Inconclusive |
|
暗示條件還未被驗證 |
IsTrue |
|
驗證條件為真 |
IsFalse |
|
驗證條件為假 |
IsInstanceOfType |
Assert.IsInstanceOf<> |
驗證實例匹配類型 |
IsNotInstanceOfType |
Assert.IsNotInstanceOf<> |
驗證實例不匹配類型 |
IsNotNull |
|
驗證條件為NULL |
IsNull |
|
驗證條件不為NULL |
Fail |
|
驗證失敗 |
另外還有一些是NUnit中的,但是MS Test框架中是沒有的:
- Assert.IsNaN
- Assert.IsEmpty
- Assert.IsNotEmpty
- Assert.Greater
- Assert.GreaterOrEqual
- Assert.Less
- Assert.LessOrEqual
- Assert.IsAssignableFrom
- Assert.IsNotAssignableFrom
- Assert.Igore
- CollectionAssert.IsEmpty
- CollectionAssert.IsNotEmpty
- StringAssert.AreEqualIgnoringCase
- StringAssert.IsMatch
- FileAssert.AreEqual
- FileAssert.AreNotEqual
9.測試技巧
有六個值得測試的具體部位,它們能夠提高你的測試水平。這六個方面可以統稱為Right_BICEP:
Right : 結果是否正確(Right)
對於測試而言,首要的也是最明顯的任務就是查看所期望的結果是否正確-驗證結果。這里的結果是指確認代碼所做的和你的期望是一致的。
B: 邊界(boundary)條件是否正確
邊界條件包括許多內容,將在下一節(2.3.邊界條件)中集中描述。
I: 是否可以檢查反向(inverse)關聯
對一些方法,可以用反向的邏輯關系來驗證它們。例如,為了檢查某條記錄是否成功的插入了數據庫,可以通過查詢這條記錄來驗證,等等。
值得注意的是,當同時編寫原方法和它的反向測試時,一些BUG可能會被兩者中都有的錯誤所掩飾。在可能的情況下,應該用不同的原理來實現反向測試。
C: 是否可以使用其它方法來跨檢查(cross-check)結果
E: 錯誤條件(error condition)是否可以重現
應該能夠通過強制引發真實世界中的錯誤-網絡斷開、程序崩潰等-來測試代碼如何處理這些問題。簡單的無效參數之類的錯誤會很簡單,但要模擬復雜的錯誤就需要一些特殊的技術。在下面的文字中,將討論使用Mock技術來解決如何強制產生錯誤的問題。
P: 性能(performance)方面是否滿足條件
這里的性能特征並不是指程序的性能本身,而是指性能的那種“隨着規模增大,問題越來越復雜”的趨勢。我們應該使用一個性能特性的快速回歸測試,避免出現某些修改使得程序變得很慢卻無法對其進行定位的情況。
10.網站推薦
1. 對比MS Test與NUnit Test框架
http://www.cnblogs.com/ColdJokeLife/p/3158812.html
2. 淺談NUnit單元測試方法小總結
http://www.ltesting.net/ceshi/ceshijishu/dycs/2011/1230/203848.html
3.NUnit之Assertion詳解
http://www.51testing.com/?uid-116228-action-viewspace-itemid-807305