一、簡介
NUnit是一款堪與JUnit齊名的開源的回歸測試框架,供.net開發人員做單元測試之用,可以從www.nunit.org網站上免費獲得,最新版本2.2.6。NUnit 2.2.6有5個下載文件,這里用的是NUnit-2.2.6-net-2.0.msi。下載后雙擊該文件,然后按提示進行安裝,這樣系統中就具備NUnit環境了。
二、配置類庫
開發工具我使用的是微軟的Visual Studio.net 2005(以下簡稱vs),打開后點擊菜單“文件”->“新建項目”,打開“新建項目”對話框:
在該對話框中,“項目類型”我選擇的是“Visual Basic”,如果想使用C#或者J#,請自行選擇“其他語言”下的“Visual C#”或“Visual J#”,反正操作差不多,下邊也都會介紹到,不過VC就免談了;“模板”我選的是“控制臺應用程序”,您也可以選其它“模板”,我看的例子創建的就是“類庫”;名稱請自行設定,VB、C#、J#項目我都建了,分別起名為NUnitVB、NUnitCS和NUnitJS,設置好后,點擊“確定”按鈕。此時項目雖已創建,但尚未保存,請點擊“文件”->“全部保存”,打開“保存項目”對話框:
通過“瀏覽”按鈕設置“位置”,我設置的是本機G:\MDZPCK\Microsoft\MySY。
下面點擊菜單“項目”->“添加引用”,打開“添加引用”對話框:
在“.NET”選項卡中找到組件名稱為nunit.framework的一項,點擊“確定”按鈕,此時在項目中就可以使用NUnit類庫了。
三、編寫用于測試的類
用于測試的類很簡單,名為Book,只有id和name兩個屬性,這兩個屬性將分別用于兩個用例當中。
下面開始編寫,請點擊菜單“項目”->“添加類”,打開“添加新項”對話框:
在該對話框中,“類”模板被默認選中,請將名稱修改為Book.vb或Book.cs、Book.jsl,然后點擊“添加”按鈕。
類創建后,需要修改代碼,VB代碼如下:
Public Class Book
Dim pid As String = Nothing
Dim pname As String = Nothing
Property id() As String
Get
Return pid
End Get
Set(ByVal Value As String)
pid = Value
End Set
End Property
Property name() As String
Get
Return pname
End Get
Set(ByVal Value As String)
pname = Value
End Set
End Property
End Class
代碼比較簡單,沒什么可說的吧?下邊是C#代碼:
using System;
using System.Collections.Generic;
using System.Text;
namespace NUnitCS
{
public class Book
{
private string pid = null;
private string pname = null;
public string id
{
get
{
return pid;
}
set
{
pid = value;
}
}
public string name
{
get
{
return pname;
}
set
{
pname = value;
}
}
}
}
也沒什么可說的吧?下邊是J#代碼:
package NUnitJS;
public class Book
{
private String pid = null;
private String pname = null;
/** @property */
public void set_id(String value)
{
pid = value;
}
/** @property */
public String get_id()
{
return pid;
}
/** @property */
public void set_name(String value)
{
pname = value;
}
/** @property */
public String get_name()
{
return pname;
}
}
可以看到,J#代碼與VB和C#代碼有些不同,因為J#的語法是從Java演變過來的,所以其屬性在定義時被拆成了set_XXX和get_XXX這樣的兩個方法。但僅有set_XXX和get_XXX這樣的兩個方法還不夠,還需要使用@property指令進行說明。雖然用不用@property指令在調用時也沒什么區別,但你可以嘗試將變量pid和pname更名為id和name,重新編譯;而后再將@property指令去掉,再重新編譯。真的不一樣。
至此,用于測試的類編寫完成了。
四、編寫測試用例
這里只用了一個類進行測試,名為BookTest,以前這樣的類可能需要繼承NUnit.Framework.TestCase類,但現在只需要對該類使用TestFixture屬性進行標識即可,而無須繼承了。BookTest類包含兩個用例,分別對應該類的testId和testName方法,即每個方法實現了一個測試用例。注意,在NUnit中,這些用來實現測試用例的方法有兩種手段進行標識:一個是以testXXX的格式來命名,一個是使用Test屬性進行標識。此外,BookTest還有Init和Dispose這兩個方法,并分別使用SetUp和TearDown屬性來進行標識,前者在每個測試方法開始之前執行,多用來做初始化;后者在每個測試方法完成之后執行,多用來清理資源。注意,這兩個方法的名稱并沒有什么限制,但必須用SetUp和TearDown屬性進行標識。另外,NUnit還提供了TestFixtureSetUp和TestFixtureTearDown屬性,功能與SetUp和TearDown類似,但前者是在所有用例執行之前做初始化、之后做清理,而后者是在每個用例執行之前做初始化、之后做清理。下面開始編寫BookTest。
點擊菜單“項目”->“添加類”,打開“添加新項”對話框,將名稱改為BookTest.vb或BookTest.cs、BookTest.jsl,然后點擊“添加”按鈕創建該類。修改代碼,VB代碼如下:
Imports NUnit.Framework
<TestFixture()> _
Public Class BookTest
Dim bo As Book = Nothing
<SetUp()> _
Public Sub Init()
Console.WriteLine("測試開始!")
bo = New Book
Console.WriteLine("book對象被初始化!")
End Sub
<Test()> _
Public Sub testId()
bo.id = "001" '設置id屬性的值為
'使用Assert查看id屬性的值是否為
Assert.AreEqual("001", bo.id)
Console.WriteLine("id屬性被測試!")
End Sub
<Test()> _
Public Sub testName()
bo.name = "ASP" '設置name屬性的值為ASP
'使用Assert查看name屬性的值是否為JSP,這是個必然出現錯誤的測試
Assert.AreEqual("JSP", bo.name)
Console.WriteLine("name屬性被測試!")
End Sub
<TearDown()> _
Public Sub Dispose()
Console.WriteLine("book對象將被清理!")
bo = Nothing
Console.WriteLine("測試結束!")
End Sub
End Class
這里Init和Dispose方法沒什么好說的,就是執行了對book對象的初始化和清理,不過testId和testName需要說明一下。前者是在對bo的id屬性進行測試,首先賦值為”001”,然后使用Assert的AreEqual方法查看id屬性中存放的值是否是期待的值,由于我的期待值也是”001”,所以執行后這個用例應該是成功的;后者則是對bo的name屬性進行測試,也是首先賦值為”ASP”,然后使用Assert的AreEqual方法查看其值是否是期待的,由于我特意將期待值設定為根本不可能的”JSP”,因此這個用例執行后會出現一個錯誤。但請注意,由于我是特意要讓測試出現錯誤,所以將期待值設定成了不可能的值,如果你是測試人員,請千萬不要這么做,否則如果別的地方導致了錯誤,很容易給自己造成不必要的麻煩。
下面簡單介紹一下上邊用到的靜態類NUnit.Framework.Assert。該類主要包含20個方法:
1.AreEqual()和AreNotEqual()方法,用來查看兩個對象的值是否相等或不等,與對象比較中使用的Equals()方法類似。
2.AreSame()和AreNotSame()方法,用來比較兩個對象的引用是否相等或不等,類似于通過“Is”或“==”比較兩個對象。
3.Contains()方法,用來查看對象是否在集合中,集合類型應與System.Collections.IList兼容。示例:
Dim o As New Object
Dim al As New ArrayList
al.Add(o)
Assert.Contains(o, al)
4.Greater()和Less()方法,用來比較兩個數值的大小,前者相當于大于號(>),后者相當于小于號(<)。
5.IsInstanceOfType()和IsNotInstanceOfType()方法,用來判斷對象是否兼容于指定類型。示例:
Dim t As Type = New Object().GetType
Dim s As String = ""
Assert.IsInstanceOfType(t, s)
由于Object是.net中所有類型的基類,String類型兼容于Object,因此這個示例是能夠運行通過的。而下邊這個示例運行將是失敗的:
Dim t As Type = New ArrayList().GetType
Dim s As String = ""
Assert.IsInstanceOfType(t, s)
6.IsAssignableFrom()和IsNotAssignableFrom()方法,用來判斷對象是否是指定類型的實例。示例:
Dim t As Type = New Object().GetType
Dim s As String = ""
Assert.IsAssignableFrom(t, s)
這個示例與之前的示例是一樣的,但由于字符串s不是Object類型的,因此無法運行通過。而下邊這個實例可以運行通過:
Dim t As Type = New String("").GetType
Dim s As String = ""
Assert.IsAssignableFrom(t, s)
7.IsFalse()和IsTrue()方法,用來查看變量是是否為false或true,如果IsFalse()查看的變量的值是false則測試成功,如果是true則失敗,IsTrue()與之相反。
8.IsNull()和IsNotNull()方法,用來查看對象是否為空和不為空。
9.IsEmpty()和IsNotEmpty()方法,用來判斷字符串或集合是否為空串或沒有元素,其中集合類型應與ICollection兼容。
10.IsNaN()方法,用來判斷指定的值是否不是數字。
11.Fail()方法,意為失敗,用來拋出錯誤。我個人認為有兩個用途:首先是在測試驅動開發中,由于測試用例都是在被測試的類之前編寫,而寫成時又不清楚其正確與否,此時就可以使用Fail方法拋出錯誤進行模擬;其次是拋出意外的錯誤,比如要測試的內容是從數據庫中讀取的數據是否正確,而導致錯誤的原因卻是數據庫連接失敗。
12.Ignore()方法,意為忽略,用來忽略后續代碼的執行,用途可以參考Fail()方法。
此外,NUnit還提供了一個專用于字符串的靜態類NUnit.Framework. StringAssert,該類主要包含4個方法:
- Contains()方法,用來查看指定的第二個字符串中是否包含了第一個字符串。
- StartsWith ()和EndsWith ()方法,分別用來查看指定的第一個字符串是否位于第二個字符串的開頭和結尾。
- AreEqualIgnoringCase()方法,用來比較兩個字符串是否相等。
下面再看一下C#代碼:
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
namespace NUnitCS
{
[TestFixture]
public class BookTest
{
Book book = null;
[SetUp]
public void Init()
{
Console.WriteLine("測試開始!");
book = new Book();
Console.WriteLine("book對象被初始化!");
}
[Test]
public void testId()
{
book.id = "001"; //設置id屬性的值為
//使用Assert查看id屬性的值是否為
Assert.AreEqual("001", book.id);
Console.WriteLine("id屬性被測試!");
}
[Test]
public void testName()
{
book.name = "ASP"; //設置name屬性的值為ASP
//使用Assert查看name屬性的值是否為JSP,這是個必然出現錯誤的測試
Assert.AreEqual("JSP", book.name);
Console.WriteLine("name屬性被測試!");
}
[TearDown]
public void Dispose()
{
Console.WriteLine("book對象將被清理!");
book = null;
Console.WriteLine("測試結束!");
}
}
}
沒什么好說的吧?下面看J#代碼:
package NUnitJS;
import System.*;
import NUnit.Framework.*;
/** @attribute TestFixture() */
public class BookTest
{
Book book = null;
/** @attribute SetUp() */
public void Init()
{
Console.WriteLine("測試開始!");
book = new Book();
Console.WriteLine("book對象被初始化!");
}
/** @attribute Test() */
public void testId()
{
book.set_id("001"); //設置id屬性的值為001
//使用Assert查看id屬性的值是否為001
Assert.AreEqual("001", book.get_id());
Console.WriteLine("id屬性被測試!");
}
/** @attribute Test() */
public void testName()
{
book.set_id("ASP"); //設置name屬性的值為ASP
//使用Assert查看name屬性的值是否為JSP,這是個必然出現錯誤的測試
Assert.AreEqual("JSP", book.get_name());
Console.WriteLine("name屬性被測試!");
}
/** @attribute TearDown() */
public void Dispose()
{
Console.WriteLine("book對象將被清理!");
book = null;
Console.WriteLine("測試結束!");
}
}
改好后,點擊菜單“調試”->“啟動調試”或按F5鍵運行程序。等等,main函數里頭好象一句代碼也沒寫過呢吧?沒錯,一句也沒寫,不過你照做就可以了。在看到黑屏一閃之后,編碼工作完成。
五、運行NUnit
編碼完成后,就可以使用NUnit測試了。NUnit有兩種界面,一種是命令行的,一種是可視化的,我使用的就是后者。點擊“開始”菜單->“所有程序”->“NUnit-Net-2.0 2.2.6”->“NUnit-Gui”,打開NUnit的可視化界面:
點擊菜單“File”->“Open”,打開剛才運行生成的可執行文件:
此時就可以使用BookTest類對Book類進行測試了。請首先選擇testId,點擊“Run”按鈕,運行結果如下圖:
testId前的灰點變綠,而且進度條顯示為綠條,這表明運行成功。下面再選擇BookTest,點擊“Run”按鈕,運行結果如下圖:
testId前的點依然是綠色,但testName前的點是紅色,而且進度條顯示為紅條,這表明testName中存在錯誤。不過這個錯誤是預計之內的,如果不想看到,可以在vs中將testName()方法中的”JSP”改成”ASP”,然后重新運行。此時無須重新啟動NUnit,NUnit會自動加載重新編寫好的文件。此時再運行BookTest,進度條已不是紅色,而是綠色了。
六、說明
本文是對《NUnit學習筆記》的修正,NUnit和Visual Studio.net都使用了新版本。NUnit 2.2.6對2.2.0進行了很多擴展,這從對NUnit.Framework.Assert和NUnit.Framework.StringAssert的介紹就可以看出來。
文章來源于領測軟件測試網 http://www.kjueaiud.com/