NUnit是一個專門針對于.NET來寫的單元測試框架,它是xUnit體系中的一員,在xUnit體系中還有針對Java的JUnit和針對C++的CPPUnit,在開始的時候NUnit和xUnit體系中的大多數(shù)的做法一樣,僅僅是將Smalltalk或者Java版本轉(zhuǎn)換而來,但是在.NET2.0之后它加入了一些特有的做法。NUnit的官方網(wǎng)站是:http://www.nunit.org/,目前的新版本是:2.6.2。
NUnit下載與安裝
NUnit的每個版本都提供了兩種形式的下載:安裝文件和免安裝方式,分別是*.msi格式和*.zip格式。前者需要安裝才能使用,并且會在安裝過程中創(chuàng)建一些快捷方式和注冊NUnit的dll到GAC,這樣以后編寫NUnit測試類的時候添加NUnit的dll像添加.Net Framework的dll一樣。如果是下載的zip格式的文件,則不會創(chuàng)建快捷方式和注冊dll,在編寫單元測試類時需要手動指定NUnit的dll的路徑。
NUnit的運行有三種方式:命令行和圖形用戶界面。以周公當(dāng)前電腦上安裝的NUnit2.5.10為例,安裝路徑為:C:Program Files (x86)NUnit 2.5.10,其下有三個目錄:bin、doc和samples。在doc目錄下是軟件的文檔(英文),在samples目錄下則是一些樣例代碼。如果是采用免安裝模式的話,運行NUnit需要運行bin目錄下的文件,在bin目錄下有net-1.1和net-2.0兩個文件夾,分別對應(yīng).net的不同版本。
下面介紹如何以不同的方式啟動NUnit:
命令行模式:運行nunit-console.exe。
圖形用戶界面模式:運行nunit.exe。
并行(parallel)模式:運行pnunit-launcher.exe。
注意:.Net2.0版本的NUnit是使用/platform:anycpu參數(shù)來編譯的,我們知道這樣的結(jié)果是運行在x86的系統(tǒng)上會被JIT編譯成32位的程序,而在x64的系統(tǒng)上會被JIT編譯成64位的程序。如果使用NUnit在x64系統(tǒng)上測試32位的程序會帶來問題。為了避免這個問題,可以使用nunit-agent-x86.exe/nunit-x86.exe來測試,因為在編譯的時候使用了/platform:x86作為編譯參數(shù)。
下圖是運行NUnit的GUI界面:
NUnit的常用Attribute標記
這些都是可以用來作為類或者方法的屬性,它們都是System.Attribute類的直接或間接子類,有如下:
Category:用來將測試分類。這個在主界面可以看到Tests/Categories兩個選項卡,如果給方法標記了Category屬性會在Categories選項卡中看得到。
Combinatorial:用來將來測試時需要測試各種可能的組合,比如如下代碼:
[csharp] view plaincopy
[Test, Combinatorial]
public void MyTest(
[Values(1, 2, 3)] int x,
[Values("A", "B")] string s)
{
string value = x + s;
Assert.Greater(2, value.Length);
}
測試時實際會測試6種情況:MyTest(1, "A")/MyTest(1, "B")/MyTest(2, "A")/MyTest(2, "B")/MyTest(3, "A")/MyTest(3, "B")。
Culture:設(shè)置測試時的語言環(huán)境,這對我們測試一些語言敏感的場景下有用,比如DateTime.ToString()在不同語言環(huán)境下得到的字符串并不相同。
Description:用于指定測試對應(yīng)的描述,如果選擇將測試結(jié)果生成XML文件,那么會在XML文件中看到這些描述。
ExpectedException:指出執(zhí)行測試時將會拋出Exception。
Explicit:如果測試的類或者方法使用此Attribute,那么在使用帶GUI的NUnit測試時這個類或者方法必須在界面上選定才會被執(zhí)行。
Explicit:忽略某個測試類或者方法。
Maxtime:測試方法大執(zhí)行的毫秒數(shù),如果程序的執(zhí)行時間超過指定數(shù)值,那么會被認為測試失敗。
Random:用于指定如何隨機生成參數(shù)來測試方法。如下面的代碼:
[csharp] view plaincopy
[Test]
public void TestDemo1(
[Values(1, 2, 3)] int x,
[Random(-10,10,2)] int y)
{
Assert.Greater(x + y, 0);
}
表示方法TestDemo1會生成6個測試,1,2,3分別作為參數(shù)x的值與兩次從-10到10之間的隨機數(shù)y組成6次測試。
Range:指定參數(shù)的方法,如下面的方法:
[Test]
public void TestDemo2(
[Range(0, 11, 4)] int x)
{
Assert.AreEqual(x%3,0);
}
表示從0開始遞增,步長為4,且不大于11。
Repeat:將重復(fù)測試的次數(shù)。
RequiresMTA:表示測試時需要多線程單元(multi-threaded apartment)。
RequiresSTA:表示測試時需要單線程單元(single-threaded apartment)。
SetUp:在每個測試方法開始之前執(zhí)行的初始化操作。在NUnit 2.5之前要求每個類只能有一個帶SetUp屬性的實例方法,但在NUnit 2.5之后則沒有次數(shù)和必須是實例方法的限制。
TearDown:與SetUp的作用相反,是在每個測試方法執(zhí)行結(jié)束之后執(zhí)行的方法。在NUnit 2.5之前要求每個類只能有一個帶SetUp屬性的實例方法,但在NUnit 2.5之后則沒有次數(shù)和必須是實例方法的限制。
Test:用來標記需要測試的方法,在NUnit 2.5之前只能用于標記實例方法,在NUnit 2.5之后則可以用于標記靜態(tài)方法。
TestCase:標記方法具有參數(shù)并且提供了在測試時需要的參數(shù)。如下面的代碼:
[TestCase(12, 3, 4)]
[TestCase(12, 2, 6)]
[TestCase(12, 4, 3)]
public void DivideTest(int n, int d, int q)
{
Assert.AreEqual(q, n / d);
}
將會執(zhí)行三次測試,相當(dāng)于:
[Test]
public void DivideTest()
{
Assert.AreEqual(4,12/3);
}
[Test]
public void DivideTest()
{
Assert.AreEqual(6,12/2);
}
[Test]
public void DivideTest()
{
Assert.AreEqual(3,12/4);
}
TestFixture:標記一個類可能具有[Test]/[SetUp]/[TearDown]方法,但這個類不能是抽象類。
TestFixtureSetUp:標記在類中所有測試方法執(zhí)行之前執(zhí)行的方法。在NUnit 2.5之前只能在類中將此標記多使用于一個實例方法,在NUnit 2.5之后則可以標記多個方法,而且不限于實例方法還可以用于靜態(tài)方法。