通常的單元測試框架都以他們支持的語言的開頭字母加上Unit作為名字,他們統稱為xUnit框架。C++的叫做CppUnit,Java的叫做JUnit,.Net的叫做NUnit。當然不是所有的都這么命名,但大部分如此。下面我主要講解一下NUni的一些基本操作。
1:Nunit兩個重要屬性
1.1:[TestFixture]
這個是標識包含自動化測試的類,可能改成TestClass大家更加理解。但是代碼是無法編譯過去的。
1.2:[Test]
這個是標識這個方法需要自動化測試的。記得把這個屬性加在要測試的方法上。
2:編寫第一個單元測試
2.1:一個單元測試通常包含三個行為:
2.1.1:准備對象(就是對哪個對象就行操作)
2.1.2:操作對象(對對象進行一些邏輯處理)
2.1.3:斷言(Assert)和預判產生的結果對比
2.2:編寫一個判斷后綴名的方法
public bool IsValidExtensions(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentNullException("fileName"); var extension = Path.GetExtension(fileName); if (extension.Contains("pdf")) { return true; } return false; }
2.3:編寫測試方法
2.3.1:Assert這個類
Assert.IsFalse(bool condition, string message)
參數1:返回的結果 參數2:展示失敗的信息
Assert.AreEqual(int expected, int actual, string message)
參數1:期望的結果 參數2:實際的結果 參數3:展示失敗的信息
當然Assert很多方法可以自己去學習。
[Test] public void IsValidExtensions_BadExtension_ReturnsFalse() { var arithmetic=new Arithmetic(); bool restlt = arithmetic.IsValidExtensions("log.pdf"); Assert.IsFalse(restlt,"沒有返回正確值"); }
2.3.2:編譯項目然后打開Nunit,點擊NUnit的File打開這個編譯的dll文件然后如下圖

2.3.3:我們要修改單元測試方法
右鍵點擊上圖的ArithmeticTest選擇LoadFixture就會重新導入這個ArithmeticTest。ClearFixTure清理這個ArithmeticTest
2.4:使用參數重構測試
比喻上面我們的參數叫做log.pdf但是現在又要測試log.txt怎么辦,如果說2個可以寫,10個乃至100個呢不用擔心NUnit給我們提供了兩個特性
[TestCase]
ok我們來修改上面的單元測試代碼
[TestCase("log.pdf")] [TestCase("log.txt")] public void IsValidExtensions_BadExtension_ReturnsFalse(string fileName) { var arithmetic=new Arithmetic(); bool restlt = arithmetic.IsValidExtensions(fileName); Assert.IsFalse(restlt,"沒有返回正確值"); }
我們在運行NUnit看看效果:

看到效果了吧我們就出現了兩個方法。這樣一來是不是很簡單。
但是有的又說我可不可以指定我預期的效果呢,很明顯是可以的我們在此修改測試方法
[TestCase("log.pdf",true)] [TestCase("log.txt",false)] public void IsValidExtensions_BadExtension_ReturnsFalse(string fileName) { var arithmetic=new Arithmetic(); bool restlt = arithmetic.IsValidExtensions(fileName); Assert.IsTrue(restlt,"沒有返回預期的值"); }
我們運行會發現這2個都能通過編譯這里就不貼圖了。
2.5:setup和teardown
setup特性以后表示每次運行這個測試類首先就會進入這個方法相當於我們常說的構造函數
teardown表示方法運行結束以后再運行這個方法,我們常說的析構函數。
如
[setup]A()
[test]B()
[teardown]C()
運行順序是A到B到C
2.6:異常檢測
2.6.1:ExpectedException標識這種標識是很常見的一種測試異常的方法下面來看它的用法
public bool IsValidExtensions(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentNullException(); var extension = Path.GetExtension(fileName); if (extension.Contains("pdf")) { return true; } return false; } [Test] [ExpectedException(typeof(ArgumentNullException),ExpectedMessage = "值不能為 null。")] public void IsVaildFileName_EmptyFileName_ThrowException() { var arithmetic = new Arithmetic(); arithmetic.IsValidExtensions(""); }
第一個參數:表示顯示異常的類
第二個參數:表示期望的異常
注意:這個異常並沒有調用Assert因為ExpectedException本身帶有判斷。
我們看看測試結果:

表示異常和我們期待的一樣,但是這有一個問題如果我們構造函數拋出一個異常測試同樣會通過,所以就會導致測試出現了不真實性。(我測試過在構造函數拋出空異常同樣測試通過)
那么就引進了另一個異常的測試方式Lambda表達式來改造一下
[Test] public void IsVaildFileName_EmptyFileName_ThrowException() { var arithmetic = new Arithmetic(); var ex = Assert.Catch<Exception>(() => arithmetic.IsValidExtensions(string.Empty)); StringAssert.Contains("值不能為 null。", ex.Message);//可以不寫值不能為Null也能通過測試 }
這樣就避免了上面的情況,只要是lambda表達式拋出異常就通過測試否則任何地方拋出異常都不能通過測試。
2.7:忽略測試
有時候有些代碼不需要測試,但是你又把它遷入主項目那么你就可以考慮把他忽略掉(當然這種情況很少的)
[Test] [Ignore("這個方法目前不用進行測試")] public void IsVaildFileName_BadExtension_ReturnFalse() { var arithmetic = new Arithmetic(); Assert.IsTrue(arithmetic.IsValidExtensions("11")); }
測試效果:

黃色的就表示暫時不考慮測試的方法。
2.8:設置測試類別
在實際開發中可能我們很多測試,為了分開測試我們可以設置類別,也可以在測試中選擇一些分類測試下面我們看看怎么實現的
[Test] [Category("后台單元測試")] public void IsVaildFileName_BadExtension_ReturnFalse() { var arithmetic = new Arithmetic(); Assert.IsTrue(arithmetic.IsValidExtensions("11")); } [Test] [Category("前端單元測試")] public void IsVaildFileName_EmptyFileName_ThrowException() { var arithmetic = new Arithmetic(); var ex = Assert.Catch<Exception>(() => arithmetic.IsValidExtensions(string.Empty)); StringAssert.Contains("值不能為 null。", ex.Message); }
我們看看效果:

大家可以自己動手測試下,實際功能比這強大很多的。
2.9:測試類中某個屬性沒有返回值怎么辦
這個比較簡單我直接貼代碼了。
public bool IsOnline { get; set; } public void IsValidExtensions(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentNullException(); var extension = Path.GetExtension(fileName); if (!extension.Contains("pdf")) return; IsOnline = true; }
[Test] public void IsVaildFileName_BadExtension_ReturnFalse() { var arithmetic = new Arithmetic(); arithmetic.IsValidExtensions("log.pdf"); Assert.IsTrue(arithmetic.IsOnline); }
這個效果很明顯是通過的。這樣來驗證類的一個屬性(但是有一個依耐項)

以上參考單元測試的藝術
