您好,登錄后才能下訂單哦!
這篇文章給大家介紹.NET開發中的單元測試工具NUnit怎么用,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
NUnit是一個專門針對于.NET來寫的單元測試框架,它是xUnit體系中的一員,在xUnit體系中還有針對Java的JUnit和針對C++的CPPUnit,在開始的時候NUnit和xUnit體系中的大多數的做法一樣,僅僅是將Smalltalk或者Java版本轉換而來,但是在.NET2.0之后它加入了一些特有的做法。NUnit的官方網站是:http://www.nunit.org/,目前的最新版本是:2.6.2。
NUnit的每個版本都提供了兩種形式的下載:安裝文件和免安裝方式,分別是*.msi格式和*.zip格式。前者需要安裝才能使用,并且會在安裝過程中創建一些快捷方式和注冊NUnit的dll到GAC,這樣以后編寫NUnit測試類的時候添加NUnit的dll就像添加.Net Framework的dll一樣。如果是下載的zip格式的文件,則不會創建快捷方式和注冊dll,在編寫單元測試類時需要手動指定NUnit的dll的路徑。
NUnit的運行有三種方式:命令行和圖形用戶界面。以周公當前電腦上安裝的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兩個文件夾,分別對應.net的不同版本。
下面介紹如何以不同的方式啟動NUnit:
命令行模式:運行nunit-console.exe。
圖形用戶界面模式:運行nunit.exe。
并行(parallel)模式:運行pnunit-launcher.exe。
注意:.Net2.0版本的NUnit是使用/platform:anycpu參數來編譯的,我們知道這樣的結果是運行在x86的系統上會被JIT編譯成32位的程序,而在x64的系統上會被JIT編譯成64位的程序。如果使用NUnit在x64系統上測試32位的程序就會帶來問題。為了避免這個問題,可以使用nunit-agent-x86.exe/nunit-x86.exe來測試,因為在編譯的時候使用了/platform:x86作為編譯參數。
下圖是運行NUnit的GUI界面:
這些都是可以用來作為類或者方法的屬性,它們都是System.Attribute類的直接或間接子類,有如下:
Category:用來將測試分類。這個在主界面可以看到Tests/Categories兩個選項卡,如果給方法標記了Category屬性就會在Categories選項卡中看得到。
Combinatorial:用來將來測試時需要測試各種可能的組合,比如如下代碼:
[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:設置測試時的語言環境,這對我們測試一些語言敏感的場景下有用,比如DateTime.ToString()在不同語言環境下得到的字符串并不相同。
Description:用于指定測試對應的描述,如果選擇將測試結果生成XML文件,那么就會在XML文件中看到這些描述。
ExpectedException:指出執行測試時將會拋出Exception。
Explicit:如果測試的類或者方法使用此Attribute,那么在使用帶GUI的NUnit測試時這個類或者方法必須在界面上選定才會被執行。
Explicit:忽略某個測試類或者方法。
Maxtime:測試方法最大執行的毫秒數,如果程序的執行時間超過指定數值,那么就會被認為測試失敗。
Random:用于指定如何隨機生成參數來測試方法。如下面的代碼:
[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分別作為參數x的值與兩次從-10到10之間的隨機數y組成6次測試。
Range:指定參數的方法,如下面的方法:
[Test]
public void TestDemo2(
[Range(0, 11, 4)] int x)
{
Assert.AreEqual(x%3,0);
}
表示從0開始遞增,步長為4,且不大于11。
Repeat:將重復測試的次數。
RequiresMTA:表示測試時需要多線程單元(multi-threaded apartment)。
RequiresSTA:表示測試時需要單線程單元(single-threaded apartment)。
SetUp:在每個測試方法開始之前執行的初始化操作。在NUnit 2.5之前要求每個類只能有一個帶SetUp屬性的實例方法,但在NUnit 2.5之后則沒有次數和必須是實例方法的限制。
TearDown:與SetUp的作用相反,是在每個測試方法執行結束之后執行的方法。在NUnit 2.5之前要求每個類只能有一個帶SetUp屬性的實例方法,但在NUnit 2.5之后則沒有次數和必須是實例方法的限制。
Test:用來標記需要測試的方法,在NUnit 2.5之前只能用于標記實例方法,在NUnit 2.5之后則可以用于標記靜態方法。
TestCase:標記方法具有參數并且提供了在測試時需要的參數。如下面的代碼:
[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);
}
將會執行三次測試,相當于:
[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:標記在類中所有測試方法執行之前執行的方法。在NUnit 2.5之前只能在類中將此標記最多使用于一個實例方法,在NUnit 2.5之后則可以標記多個方法,而且不限于實例方法還可以用于靜態方法。
TestFixtureTearDown:標記在類中所有測試方法執行之后再執行的方法。在NUnit 2.5之前只能在類中將此標記最多使用于一個實例方法,在NUnit 2.5之后則可以標記多個方法,而且不限于實例方法還可以用于靜態方法。
Timeout:標記被測試的方法最大的執行時間,如果超出標記的時間,則會被取消執行并且被標記為測試失敗。
Values:標記作為測試方法的一系列的參數。前面的代碼實例中就有用法實例。
斷言是所有基于xUnit單元測試系列的核心,NUnit通過NUnit.Framework.Assert類提供了豐富的斷言。具體說來,NUnit總共提供了11個類別的斷言,它們是:
Equality Asserts:用于斷言對象是否相等方面的斷言,主要表現為兩個方法的重載:Assert.AreEqual()和Assert.AreNotEqual()兩種形式的重載,重載參數包括了常見的基本數值類型(int/float/double等)和引用類型(表現為使用object作為參數).
Identity Asserts:用于判斷引用類型的對象是否是同一個引用的斷言及斷言對象是否存在于某個集合中,如Assert.AreSame、Assert.AreNotSame及Assert.Contains。
Condition Asserts:用于某些條件的斷言,如:Assert.IsTrue、Assert.True、Assert.IsFalse、Assert.False、Assert.IsNull、Assert.Null、Assert.IsNotNull、Assert.NotNull、Assert.IsNaN、Assert.IsEmpty及Assert.IsNotEmpty。
Comparisons Asserts:用于數值及實現了IComparable接口的類型之間的斷言,如Assert.Greater(大于)、Assert.GreaterOrEqual(大于或等于)、Assert.Less(小于)、Assert.LessOrEqual(小于或等于)。
Type Asserts:用于類型之間的判斷,比如判斷某個實例是否是某一類型或者是從某個類型繼承,如:Assert.IsInstanceOfType、Assert.IsNotInstanceOfType、Assert.IsAssignableFrom、Assert.IsNotAssignableFrom。在NUnit 2.5之后就增加了泛型方法,如Assert.IsInstanceOf<T>、Assert.IsNotInstanceOf<T>、Assert.IsAssignableFrom<T>、Assert.IsNotAssignableFrom<T>。。
Exception Asserts:有關異常方面的斷言,如Assert.Throws/Assert.Throws<T>、Assert.DoesNotThrow、Assert.Catch/Assert.Catch<T>。
Utility Methods:用于精確控制測試過程,總共有四個方法,分別是:Assert.Pass、Assert.Fail、Assert.Ignore、Assert.Inconclusive。Assert.Pass和Assert.Fail是相反的,前者是表示將立即終止測試并將測試結果標識為成功通過測試,后者是立即終止測試并將測試結果標識為測試失敗。Assert.Ignore表示忽略測試,這個標記可以用于標識測試方法或者測試的類。
StringAssert:用于字符串方面的斷言,提供的方法有StringAssert.Contains、StringAssert.StartsWith、StringAssert.EndsWith、StringAssert.AreEqualIgnoringCase及StringAssert.IsMatch。
CollectionAssert:關于集合方面的斷言,提供的方法有CollectionAssert.AllItemsAreInstancesOfType、CollectionAssert.AllItemsAreNotNull、CollectionAssert.AllItemsAreUnique、CollectionAssert.AreEqual、CollectionAssert.AreEquivalent、CollectionAssert.AreNotEqual、CollectionAssert.AreNotEquivalent、CollectionAssert.Contains、CollectionAssert.DoesNotContain、CollectionAssert.IsSubsetOf、CollectionAssert.IsNotSubsetOf、CollectionAssert.IsEmpty、CollectionAssert.IsNotEmpty和CollectionAssert.IsOrdered。
FileAssert:用于文件相關的斷言,主要提供兩個方法:FileAssert.AreEqual和FileAssert.AreNotEqual。
DirectoryAssert:用于文件夾的斷言,提供的方法有:DirectoryAssert.AreEqual、DirectoryAssert.AreNotEqual、DirectoryAssert.IsEmpty、DirectoryAssert.IsNotEmpty、DirectoryAssert.IsWithin和DirectoryAssert.IsNotWithin。
第一次打開NUnit時會是一個空白界面,如下圖所示:
首先我們需要創建一個NUnit項目,點擊[File]->[New Project]會彈出一個保存NUnit項目的對話框,選擇合適的路徑并輸入合適的名稱(注意文件后綴名為.nunit),然后點擊保存按鈕,這樣就創建了一個NUnit測試項目。以后我們就可以再次打開這個項目了。
此時這個NUnit項目中還不包含任何單元測試用例,我們需要創建包含測試用例的項目。打開Visual Studio創建一個類庫項目(在真實項目中通常做法是向當前解決方案中添加類庫項目,這樣便于解決dll引用問題),接著我們需要添加NUnit的引用,這取決于我們是采用安裝方式還是免安裝方式,通常情況下我們只需要添加對nunit.framework(對應的dll是unit.framework.dll)的引用就夠了。
這里周公采用的示例代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using NUnit.Framework; namespace UnitTestDemo { [TestFixture] public class NUnitTestDemo { private IList<int> intList = new List<int>(); [SetUp] [Category("NA")] public void BeforeTest() { Console.WriteLine("BeforeTest"); } [TestFixtureSetUp] [Category("NA")] public void BeforeAllTests() { Console.WriteLine("BeforeAllTests"); } [TearDown] [Category("NA")] public void AfterTest() { Console.WriteLine("AfterTest"); } [TestFixtureTearDown] [Category("NA")] public void AfterAllTests() { Console.WriteLine("AfterAllTests"); } [Test] [Category("NA")] public void Test1() { Console.WriteLine("Test1"); } [Test] [Category("NA")] public void Test2() { Console.WriteLine("Test2"); } [Test] public void TestFloat() { float value = 0.9999999999999999999999999999f; //value = 0.9999999999999999999999999999; Console.WriteLine("float value:" + value); Assert.AreEqual(value, 1f); Console.WriteLine("TestFloat"); } [Test] public void TestDouble() { double value = 0.9999999999999999999999999999d; Console.WriteLine("double value:" + value); Assert.AreEqual(value, 1d); Console.WriteLine("Test2"); } [Test] public void TestDecimal() { decimal value = 0.9999999999999999999999999999M; Console.WriteLine("decimal value:" + value); Assert.AreEqual(value, 1M); Console.WriteLine("Test2"); } [Test,Repeat(3)] public void TestIntList2() { Assert.AreEqual(0, intList.Count); } [Test] public void TestIntList1() { intList.Add(1); Assert.AreEqual(1, intList.Count); } [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); } [Test, Combinatorial,Description("This is used for show Combinatorial")] public void MyTest( [Values(1, 2, 3)] int x, [Values("A", "B")] string s) { string value = x + s; Assert.Greater(2, value.Length); } [Test] public void TestDemo1( [Values(1, 2, 3)] int x, [Random(-10,10,2)] int y) { Assert.Greater(x + y, 0); } [Test] public void TestDemo2( [Range(0, 11, 4)] int x) { Assert.AreEqual(x%3,0); } } }
編譯項目生成dll。我們就可以在NUnit主界面上點擊[Project]->[Add Assembly...]來添加剛才編譯生成的dll,加載成功后界面如下所示:
點擊界面上的[Run]按鈕就可以開始測試了。注意這種方式下是測試所有的測試方法,如果我們只想測試某幾個方法,可以勾選方面前面的復選框(默認情況下復選框不出現,需要按照點擊[Tools]->[Setting]打開設置界面,然后點擊在[GUI]下面找到[Tree Display],勾選上“Show CheckBoxes”即可)。
如果我們只是想單獨測試某個方法,那就更簡單了——直接雙擊那個測試方法即可。
有時候我們進行測試時還會用到一些config文件里面的配置信息,如在app.config/web.config中保存數據庫連接字符串信息及其他的配置信息,為了能讓NUnit測試時能讀取app.config/web.config中保存的配置信息,我們需要對NUnit進行配置。
為了演示,我們制定以下信息:
項目名稱:UnitTestDemo
項目位置:D:\BlogCode\UnitTestDemo\
項目編譯模式(Debug/Release):Debug
為了演示剛才的如何對config文件中保存的數據進行測試,我們在剛才的代碼基礎上編寫了三個測試用例,代碼如下:
[Test] public void Test0_51CTOBlog() { StringAssert.AreEqualIgnoringCase(ConfigurationManager.AppSettings["51ctoBlog"], "http://zhoufoxcn.blog.51cto.com"); } [Test] public void Test0_CSDNBlog() { StringAssert.AreEqualIgnoringCase(ConfigurationManager.AppSettings["CSDNBlog"], "http://blog.csdn.net/zhoufoxcn"); } [Test] public void Test0_SinaWeiBo() { StringAssert.AreEqualIgnoringCase(ConfigurationManager.AppSettings["SinaWeiBo"], "http://weibo.com/zhoufoxcn"); }
同時在app.config文件的appSettings節點增加以下數據:
<appSettings> <add key="51ctoBlog" value="http://zhoufoxcn.blog.51cto.com"/> <add key="CSDNBlog" value="http://blog.csdn.net/zhoufoxcn"/> <add key="SinaWeiBo" value="http://weibo.com/zhoufoxcn"/> </appSettings>
如果不在NUnit上做任何設置,我們會得到錯誤的結果,如下圖所示:
這時,我們可以按照如下步驟配置,點擊[Project]-[Edit...]打開如下界面:
在上圖的界面中設置ApplicationBase為當前要測試的dll所在的路徑,本例中為:D:\BlogCode\UnitTestDemo\bin\Debug(注意如果復制全路徑到文本框中NUnit會自動更改為相對路徑),因為當前項目是名為UnitTestDemo的類庫項目,所以對應config文件名稱為UnitTestDemo.dll.config,將其填入Configuration File Name后面的文本框中,然后我們再次點擊[Run]按鈕就會看到測試通過。
作為xUnit體系中的一員,NUnit確實給.Net開發人員進行單元測試帶來了不少方便,在早期我們一直都是使用NUnit進行單元測試的。但是也存在著一些不足之處,比如:1.在xUnit體系中的JUnit是在測試每個方法時都是新生成一個實例,而在NUnit中確實一個TestFixture只會生成一個實例,這樣一來如果對要包含單元測試類中的實例數據進行更改會可能會影響到其它的測試方法(像JUnit那樣每次都生成一個實例則不會產生這種情況)。2.早期大多數人以為像JUnit中一樣,[SetUp]、[TearDown]只會在所有測試前、后分別執行一次,實際情況是在每個測試前、后都會執行一次,為了達到JUnit中[SetUp]、[TearDown]這樣的效果,只能新增TestFixtureSetUp、TestFixtureTearDown屬性。除此之外,還存在一些缺點和不足。
關于.NET開發中的單元測試工具NUnit怎么用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。