轉載:http://hi.baidu.com/grayworm/item/38e246165aa7b9433a176e90
NUnit是一個單元測試框架,專門針對於.NET來寫的,它是是xUnit的一員。NUnit完全由C#語言來編寫,並且編寫時充分利用了許多.NET的特性,比如反射,客戶屬性等等.
最重要的一點是它適合於所有.NET語言.
單元測試:
作為程序員在開發過程中,不可避免地要對軟件的類及其方法進行測試。
在Web頁面的測試過程中,好多朋友喜歡把測試結果使用Response.Write()顯示在頁面上。而在類庫組件的開發時,由於沒有可視化界面,有時不得不為該類庫添模一個測試的項目(Console,WinForm,ASP.NET等),在該項目中調用類庫組件的功能,以查看測試結果。
上面這種測試不是我們推薦的方法,因為我們在測試的時候應遵循以下原則:
盡量不要破壞原有的代碼結構,即不要在原代碼中添加一些冗余的測試代碼。
測試模塊應盡可能完整地展現測試結果。
測試模塊不應用完即扔掉,要保存以備后續的維護測試。
一、NUnit運行界面
《圖1》
在右邊有一個進度條,如果所有測試案例運行成功,就為綠色,反之如果有一個不成功,則為紅色,但也有黃色的.
綠色 描述目前所執行的測試都通過
黃色 意味某些測試忽略,但是這里沒有失敗
紅色 表示有失敗
左邊的樹狀目錄是我們們編寫的每一個測試單元。
底部的狀態條
狀態:當所有測試完成時,狀態變為Completed.運行測試中,狀態是Running: <test-name>
Test Cases:說明加載的程序集中測試案例的總個數。這也是測試樹里葉子節點的個數。
Tests Run: 已經完成的測試個數。
Failures: 到目前為止,所有測試中失敗的個數.
Time: 顯示運行測試時間(以秒計)
二、在VS2008中配置NUnit進行測試
1.新建一個類庫項目。
2.在解決方案中的項目圖標上右擊,選擇“屬性”。
3.點擊左邊的“調試”標簽
4.在“啟動操作”中選擇“啟動外部程序”,並指明NUnit程序的運行路徑。
5.在啟動選項中的“工作目錄”下,指明當前類庫項目的DLL文件的所在路徑。

《圖2》
6.運行當前類庫項目,我們會發現NUnit被啟動起來了。
三、安裝Unit與使用
請到http://www.nunit.org/download.html下載NUnit,然后雙擊安裝即可。
1.我們要使用NUnit對類庫組件進行測試時,一般我們會新建一個測試類文件或新建一個測試項目。
2.為測試項目添加引用“nunit.framework”
3.在測試類文件中添加using NUnit.Framework;語句
4.在該類文件或測試項目中編寫測試代碼,然后使用NUnit運行我們的測試代碼以觀察測試結果。
四、NUnit中的常用Attribute
所有NUnit屬性都包含在Nunit.Framework命名空間里。測試項目必須引用框架的程序集,即nunit.framework.dll.
1.TestFixtureAttribute
用來修飾測試類。這個屬性標記一個類包含了測試方法。
被TestFixtureAttribute修飾的類需滿足以下限制
a.必須是一個public類型,否則NUnit不會識別它。
b.它必須有一個缺省的構造子,否則Nunit不能構建他。
c.構造子不應該有任何方面的負面影響,因為在一個對話的過程中,NUnit可能構造類多次。
如:
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
// ...
}
2.TestAttribute
用來修飾測試方法。Test屬性標記某個類的某個方法為一個測試方法,而且此類必需已經標記為一個TestFixture。
一個測試方法的簽名定義如下:
public void MethodName()
注意:測試方法必須沒有參數。如果程序員將測試方法標記為不正確的簽名,它不會運行。
如:
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[Test]
public void Add()
{
//...
}
}
3.SetUpAttribute
用來修飾方法。所屬的類必需已經標記為一個TestFixture。一個TestFixture可以僅有一個SetUp方法。如果有多個定義,TestFixture也會編譯成功,但是測試不會運行。SetUpAttribute標記的方法是在每個測試方法被調用之前來完成的。
如:
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[SetUp]
public void Init()
{ /* ... */ }
[TearDown]
public void Dispose()
{ /* ... */ }
[Test]
public void Add()
{ /* ... */ }
}
SetUp屬性是從任何基類繼承而來。因此,如果基類已經定義了一個SetUp方法,那么這個方法會在每個派生的類的測試方法之前調用。如果你打算在派生類里加入更多的SetUp功能,你需要將方法標記為適當的屬性,然后調用基類方法。
SetUpAttribute使用案例:
如:我們以測試加減法為例
using System;
using NUnit.Framework;
[TestFixture]
public class NumersFixture
{
[Test]
public void AddTwoNumbers()
{
int a=1;
int b=2;
int sum=a+b;
Assert.AreEqual(sum,3);
}
[Test]
public void MultiplyTwoNumbers()
{
int a = 1;
int b = 2;
int product = a * b;
Assert.AreEqual(2, product);
}
}
不難看出兩個測試方法中有重復的代碼,如何去除重復的代碼呢?我們可以提取這些代碼到一個獨立的方法,然后標志這個方法為SetUp 屬性,這樣2個測試方法可以共享對操作數的初始化了,這里是改動后的代碼:
using System;
using NUnit.Framework;
[TestFixture]
public class NumersFixture
{
private int a;
private int b;
[SetUp]
public void InitializeOperands()
{
a = 1;
b = 2;
}
[Test]
public void AddTwoNumbers()
{
int sum=a+b;
Assert.AreEqual(sum,3);
}
[Test]
public void MultiplyTwoNumbers()
{
int product = a * b;
Assert.AreEqual(2, product);
}
}
這樣NUnit將在執行每個測試前執行標記SetUp屬性的方法.在本例中就是執行InitializeOperands()方法.記住,這里這個方法必須為public,不然就會有以下錯誤:Invalid Setup or TearDown method signature
4.TearDownAttribute
用來修飾方法。所屬的類必需已經標記為一個TestFixture。一個TestFixture可以僅有一個TearDown方法。如果有多個定義,TestFixture也會編譯成功,但是測試不會運行。被TearDownAttribute修飾的方法是每個測試方法被調用之后來執行的。
如:
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[SetUp]
public void Init()
{ /* ... */ }
[TearDown]
public void Dispose()
{ /* ... */ }
[Test]
public void Add()
{ /* ... */ }
}
TearDown屬性是從任何的基類繼承而來。因此,如果基類已經定義了一個TearDown方法,那么這個方法會在每個派生的類的測試方法之后調用。如果你打算在派生類里加入更多的TearDown功能,你需要將方法標記為適當的屬性,然后調用基類方法。
5.TestFixtureSetUpAttribute
用來修飾方法。所屬的類必需已經標記為一個TestFixture。這些個屬性標記的方式在fixture任何測試執行之前完成。TestFixture可以僅有一個TestFixtureSetUp方法。如果定義了多個,TestFixture可以成功編譯,但是測試不會被執行。
6.TestFixtureTearDownAttribute
用來修飾方法。所屬的類必需已經標記為一個TestFixture。這些個屬性標記的方式在fixture任何測試執行之后完成。TestFixture可以僅有一個TestFixtureTearDownAttribute方法。如果定義了多個,TestFixture可以成功編譯,但是測試不會被執行。
如:
namespace NUnit.Tests
{
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[TestFixtureSetUp]
public void Init()
{ /* ... */ }
[TestFixtureTearDown]
public void Dispose()
{ /* ... */ }
[Test]
public void Add()
{ /* ... */ }
}
}
SetUp/TearDown方法提供達到測試隔離性的目的.SetUp確保共享的資源在每個測試運行前正確初始化,TearDown確保沒有運行測試產生的遺留副作用. TestFixtureSetUp/TestFixtureTearDown同樣提供相同的目的,但是卻在test fixture范圍里
我們寫一個簡單的測試來說明什么方法調用了,怎么合適調用
using System;
using NUnit.Framework;
[TestFixture]
public class LifeCycleContractFixture
{
[TestFixtureSetUp]
public void FixtureSetUp()
{
Console.Out.WriteLine("FixtureSetUp");
}
[TestFixtureTearDown]
public void FixtureTearDown()
{
Console.Out.WriteLine("FixtureTearDown");
}
[SetUp]
public void SetUp()
{
Console.Out.WriteLine("SetUp");
}
[TearDown]
public void TearDown()
{
Console.Out.WriteLine("TearDown");
}
[Test]
public void Test1()
{
Console.Out.WriteLine("Test 1");
}
[Test]
public void Test2()
{
Console.Out.WriteLine("Test 2");
}
}
運行結果:
FixtureSetUp
SetUp
Test 1
TearDown
SetUp
Test 2
TearDown
FixtureTearDown
7.ExpectedExceptionAttribute
修飾方法,用來測試一個方法是否拋出了指定的異常。本屬性有兩種重載方式。第一種是一個Type,此Type為期望的異常的精確類型。 第二種是一個期望的異常全名的字符串
在執行測試時,如果它拋出了指定的異常,那么測試通過。如果拋出一個不同的異常,測試就失敗。如果拋出了一個由期望異常繼承而來的異常,這也是成功的。
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void ExpectAnExceptionByType()
{ /* ... */ }
[Test]
[ExpectedException("System.InvalidOperationException")]
public void ExpectAnExceptionByName()
{ /* ... */ }
}
8.CategoryAttribute
修飾方法或修飾類。用來把測試分組,可以使用NUnit的Categories選項卡選擇要測試的組,或排除一些組。
對類分組:
using System;
using NUnit.Framework;
[TestFixture]
[Category("LongRunning")]
public class LongRunningTests
{
// ...
}
對方法分組:
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[Test]
[Category("Long")]
public void VeryLongTest()
{ /* ... */ }
}
下面我們編寫三個測試方法,並分為兩組“Compare”和“TestNull”,在NUnit中測試“Compare”組的內容:
第一步:點擊左側的“Categories”選項卡
第二步:在“Available Categories”列表框中選擇“Compare”,點擊“Add”按鈕
第三步:點擊左側“Test”選項卡,點擊樹狀目錄中的“Class1”,點擊“Run”按鈕
我們發現只有TestTowInstanceName和TestTowInstanceEqual兩個測試方法運行了,而TestNull沒有運行,因此TestNull不是“Compare”組的。
9.ExplicitAttribute
用來修飾類或方法。Explicit屬性會忽略一個測試或測試Fixture,直到它被顯式的選擇運行。。如果test和test fixture在執行的過程中被發現,就忽略他們。所以,這樣一來進度條顯示為黃色,因為有test或test fixture忽略了。
修飾類:
using System;
using NUnit.Framework;
[TestFixture, Explicit]
public class ExplicitTests
{
// ...
}
修飾方法:
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[Test, Explicit]
public void ExplicitTest()
{ /* ... */ }
}
10.IgnoreAttribute
用來修飾類或方法。由於種種原因,有一些測試我們不想運行.當然,這些原因可能包括你認為這個測試還沒有完成,這個測試正在重構之中,這個測試的需求不是太明確.但你有不想破壞測試,不然進度條可是紅色的喲.怎么辦?使用Ignore屬性.你可以保持測試,但又不運行它們。
這個特性用來暫時不運行一個測試或fixture。比起注釋掉測試或重命名方法,這是一個比較好的機制,因為測試會和余下的代碼一起編譯,而且在運行時有一個不會運行測試的標記,這樣保證不會忘記測試。
修飾類:
using System;
using NUnit.Framework;
[TestFixture]
[Ignore("Ignore a fixture")]
public class SuccessTests
{
// ...
}
修飾方法
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[Test]
[Ignore("Ignore a test")]
public void IgnoredTest()
{ /* ... */ }
}