單元測試是代碼正確性驗證的最重要的工具,也是系統測試當中最重要的環節。也是唯一需要編寫代碼才能進行測試的一種測試方法。在標准的開發過程中,單元測試的代碼與實際程序的代碼具有同等的重要性。每一個單元測試,都是用來定向測試其所對應的一個單元的數據是否正確。
一、單元測試具有一下幾個好處
1、能夠協助程序員盡快找到BUG的具體位置
2、能夠讓程序員對自己的程序更有自信
3、能夠讓程序員在提交項目之前就將代買變得更加健壯
4、能夠協助程序員更好的進行開發
5、能夠向其他程序員展現你的程序該如何調用
二、單元測試任務包括
1、模塊接口測試
測試接口正確與否應該考慮下列因素
(1)、輸入的實際參數與形式參數的個數是否相同;
(2)、輸入的實際參數與形式參數的屬性是否匹配;
(3)、輸入的實際參數與形式參數的量綱是否一致;
(4)、調用其他模塊時所給實際參數的個數是否與被調模塊的形參個數相同;
(5)、調用其他模塊時所給實際參數的屬性是否與被調模塊的形參屬性匹配;
(6)、調用其他模塊時所給實際參數的量綱是否與被調模塊的形參量綱一致;
(7)、 調用預定義函數時所用參數的個數、屬性和次序是否正確;
(8)、是否存在與當前入口點無關的參數引用;
(9)、是否修改了只讀型參數;
(10)、對全程變量的定義各模塊是否一致;
(11)、是否把某些約束作為參數傳遞。
(2)、輸入的實際參數與形式參數的屬性是否匹配;
(3)、輸入的實際參數與形式參數的量綱是否一致;
(4)、調用其他模塊時所給實際參數的個數是否與被調模塊的形參個數相同;
(5)、調用其他模塊時所給實際參數的屬性是否與被調模塊的形參屬性匹配;
(6)、調用其他模塊時所給實際參數的量綱是否與被調模塊的形參量綱一致;
(7)、 調用預定義函數時所用參數的個數、屬性和次序是否正確;
(8)、是否存在與當前入口點無關的參數引用;
(9)、是否修改了只讀型參數;
(10)、對全程變量的定義各模塊是否一致;
(11)、是否把某些約束作為參數傳遞。
(12)、文件使用前是否已經打開;
(13)、是否處理了文件尾;
(14)、是否處理了輸入/輸出錯誤;
(15)、輸出信息中是否有文字性錯誤;
(13)、是否處理了文件尾;
(14)、是否處理了輸入/輸出錯誤;
(15)、輸出信息中是否有文字性錯誤;
2、模塊局部數據結構測試
檢查局部數據結構是為了保證臨時存儲在模塊內的數據在程序執行過程中完整、正確。局部數據結構往往是錯誤的根源,應仔細設計測試用例
應該考慮下列因素
(1)、不合適或不相容的類型說明;
(2)、變量無初值;
(3)、變量初始化或省缺值有錯;
(4)、不正確的變量名(拼錯或不正確地截斷);
(5)、出現上溢、下溢和地址異常。
(2)、變量無初值;
(3)、變量初始化或省缺值有錯;
(4)、不正確的變量名(拼錯或不正確地截斷);
(5)、出現上溢、下溢和地址異常。
3、模塊中所有獨立執行測試
應該考慮下列因素
(1)、誤解或用錯了算符優先級;
(2)、混合類型運算;
(3)、變量初值錯;
(4)、精度不夠;
(5)、表達式符號錯。
(2)、混合類型運算;
(3)、變量初值錯;
(4)、精度不夠;
(5)、表達式符號錯。
(6)、不同數據類型的對象之間進行比較;
(7)、錯誤地使用邏輯運算符或優先級;
(8)、因計算機表示的局限性,期望理論上相等而實際上不相等的兩個量相等;
(9)、比較運算或變量出錯;
(10)、循環終止條件或不可能出現;
(7)、錯誤地使用邏輯運算符或優先級;
(8)、因計算機表示的局限性,期望理論上相等而實際上不相等的兩個量相等;
(9)、比較運算或變量出錯;
(10)、循環終止條件或不可能出現;
4、模塊的各條錯誤處理測試
應該考慮下列因素
(1)、輸出的出錯信息難以理解;
(2)、記錄的錯誤與實際遇到的錯誤不相符;
(3)、在程序自定義的出錯處理段運行之前,系統已介入;
(4)、異常處理不當;
(5)、錯誤陳述中未能提供足夠的定位出錯信息。
(2)、記錄的錯誤與實際遇到的錯誤不相符;
(3)、在程序自定義的出錯處理段運行之前,系統已介入;
(4)、異常處理不當;
(5)、錯誤陳述中未能提供足夠的定位出錯信息。
三、常用的測試方法
1.測試異常
可以直接對方法進行異常測試,也可以對模擬對象進行異常測試,但是,對模擬對象進行異常測試,很少用,所以,這里就介紹對方法的異常測試。請看如下代碼,當用戶名為空的時候,拋出異常。
例如
C# 代碼
復制



public bool Valid(string userName, string passWord)

{
if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException("userName is null");
var isValid = userName == "admin" && passWord == "123456";
Log.Write(userName);
return isValid;
}

測試代碼如下
C# 代碼
復制



[Test]


[ExpectedException(typeof(ArgumentNullException))]

public void Vaild_Throw_Test()

{
MyLogin l = new MyLogin();
l.Valid("", "123456");
}

這里需要特性“ExpectedException”,意思是期待拋出一個異常。這里不需要再進行斷言了,拋出異常后,后面的代碼也就不會執行了。
2.測試返回值
這里主要講測試模擬對象的返回值。這里用到了一個LastCall的一個類,比較常用,一些輔助測試的功能,都在該類中。
測試代碼如下
C# 代碼
復制


[Test]

public void Valid_Return()

{
MockRepository mock = new MockRepository();
var log = mock.DynamicMock<ILog>();
using (mock.Record())
{
log.WriteLog("admin");
LastCall.Return(0);
}
var returnValue = log.WriteLog("admin");
Assert.AreEqual(returnValue, 0);
} 
3.測試模擬對象的參數傳遞
當調用模擬對象時,可能需要傳遞參數,如果參數的值不一至時,會導致測試失敗,比如:我需要傳遞一個字符串,其中包含了一個GUID+UserName,這里GUID可能我們無法模擬,所以,測試參數時,只需要測試UserName就可以。
方法代碼如下:
C# 代碼
復制



public bool Valid_Paramter(string userName, string passWord)

{
Log.Write(Guid.NewGuid() + userName);
return userName == "admin" && passWord == "123456";
}

測試代碼如下:
C# 代碼
復制


[Test]

public void Valid_Paramter()

{
MockRepository mock = new MockRepository();
var log = mock.DynamicMock<ILog>();
using (mock.Record())
{
log.Write("admin");
LastCall.Constraints(Rhino.Mocks.Constraints.Text.Contains("admin"));
}
MyLogin login = new MyLogin();
login.Log = log;
var valid = login.Valid_Paramter("admin", "123456");
Assert.AreEqual(valid, true);
mock.VerifyAll();
}