Nunit工具作C#的單元測試javascript
學習心得php
編寫人:羅旭成html
時間:2013年9月2日星期一java
單元測試是針對最小的可測試軟件元素(單元)的,它所測試的內容包括單元的內部結構(如邏輯和數據流)以及單元的功能和可觀測的行爲。使用白盒測試方法測試單元的內部結構,使用黑盒測試方法測試單元的功能和可觀測的行爲。正則表達式
因爲開發方式的不一樣,單元測試通常劃分方法以下:數據庫
1. 面向對象的軟件開發:以Class(類)做爲測試的最小單元。以方法的內部結構做爲測試的重點。網絡
2. 結構化的軟件開發:以模塊(函數、過程)做爲測試的最小單元。多線程
開發人員在寫代碼的時候都有本身的習慣,好比在寫一個新的類的時候,類的名稱有的用英語命名,有的用漢語拼音命名。而對於註釋而言,有的存在一部分,有的從頭至尾根本沒有註釋(這樣的代碼讓開發人員過半年本身再看,他本身也可能不知道這段代碼實現的是什麼功能)那麼是否有一段可用代碼編寫規範在執行,開發人員是否都按規範來進行開發,一段開發人員本身都看不明白的代碼,該如何進行單元測試?特別是對公用的方法要進行註釋,這樣會減小單元測試的時間。可見規範化的代碼編寫是進行單元測試必不可少的一部分。框架
在進行單元測試以前須要弄清楚被測試代碼實現的功能和相應的邏輯關係;同時還要考慮到測試的輸入內容。也就是說,測試用例的設計。用例的設計要保證面面俱到,是否覆蓋了每一條路徑。而如何作到面面俱到這就須要開發人員對每一個函數進行詳細的分析,將分析和討論的結果納入相關的測試庫中。初期工做的進度慢並沒關係,只要能作得很詳細對於之後的測試仍是有很大的幫助。或許之後的測試中,只要直接調用原來寫過的測試類庫,修改部分簡單的語句就能夠實現新模塊的單元測試了。dom
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.一、新建測試項目UnitTestApp(示例爲簡單的控制檯應用程序),引入nunit.framework類庫(默認安裝後文件所在路徑:C:\Program Files \NUnit 2.6\bin\framework\nunit.framewor.dll)
3.二、添加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.三、新增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表示具體的測試用例。能夠看到單元測試中最重要的是斷言,其餘徹底交給框架自動化。測試結果能夠經過插件及時看到:
測試例子程序:
1) 準備測試所需的條件
2) 調用要測試的方法
3) 驗證被測方法的行爲和指望的行爲是否一致
4) 完成後清理各類資源
1) 使用using聲明引用必要的NUnit類(並添加一個指向NUnitDll的引用)
2) 定義一個測試類,必須是Public的、包換一個public的沒有參數的構造函數,而且在類定義上加上[TestFixture]attribute標記。(代表是測試類)
3) 在測試類中包含用[Test]attribute標記的方法。(代表是測試方法)
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);
這些方法用來測試第二個目錄是否是第一個目錄的子(孫子等)目錄。
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]:測試用例必須的在多線程、單線程、獨立的線程狀態下運行。
1、簡介
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] |
定義標識分組。 |
3、同時支持NUnit和MSTest
經過上面的介紹,咱們能夠看到這兩個框架只是標籤的寫法不同,它們的具體功能都是同樣的。
因此能夠經過宏判斷來同時支持這兩個框架。
一、添加兩種框架的DLL
MSTest: Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
NUnit : nunit.framework.dll
二、在測試前添加如下代碼:
#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框架中是沒有的:
有六個值得測試的具體部位,它們可以提升你的測試水平。這六個方面能夠統稱爲Right_BICEP:
Right : 結果是否正確(Right)
對於測試而言,首要的也是最明顯的任務就是查看所指望的結果是否正確-驗證結果。這裏的結果是指確認代碼所作的和你的指望是一致的。
B: 邊界(boundary)條件是否正確
邊界條件包括許多內容,將在下一節(2.3.邊界條件)中集中描述。
I: 是否能夠檢查反向(inverse)關聯
對一些方法,能夠用反向的邏輯關係來驗證它們。例如,爲了檢查某條記錄是否成功的插入了數據庫,能夠經過查詢這條記錄來驗證,等等。
值得注意的是,當同時編寫原方法和它的反向測試時,一些BUG可能會被二者中都有的錯誤所掩飾。在可能的狀況下,應該用不一樣的原理來實現反向測試。
C: 是否可使用其它方法來跨檢查(cross-check)結果
E: 錯誤條件(error condition)是否能夠重現
應該可以經過強制引起真實世界中的錯誤-網絡斷開、程序崩潰等-來測試代碼如何處理這些問題。簡單的無效參數之類的錯誤會很簡單,但要模擬複雜的錯誤就須要一些特殊的技術。在下面的文字中,將討論使用Mock技術來解決如何強制產生錯誤的問題。
P: 性能(performance)方面是否知足條件
這裏的性能特徵並非指程序的性能自己,而是指性能的那種「隨着規模增大,問題愈來愈複雜」的趨勢。咱們應該使用一個性能特性的快速回歸測試,避免出現某些修改使得程序變得很慢卻沒法對其進行定位的狀況。
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