IntelliTest实战直通车(上集)
IntelliTest前世今生
??IntelliTest的前身是微軟研究院的白盒測試框架Pex,當(dāng)時的Pex并未集成到Visual Studio中,開發(fā)者需要單獨(dú)下載和配置,在下載時會附帶一個叫Moles的隔離框架(它更早些的名字叫Stubs)。隨著Visual Studio 2015 RC 版本的發(fā)布,Pex集成到Visual Studio中,成了IntelliTest,而Moles也升級成了Microsoft Fakes。
傳統(tǒng)單元測試
??回憶一下,寫單元測試之前,我們的開發(fā)流程一般是怎樣一個過程。
“我們很忙,一直忙著開發(fā)開發(fā),眼看就要到deadline了,加緊繼續(xù)開發(fā)開發(fā)。在這種情況下的產(chǎn)品質(zhì)量可想而知,于是耐心的測試給我們報bug,善良的用戶給我們提意見,沒辦法,要吃飯啊,我們又去改代碼,然而代碼并不是你想改,想改就能改的啊,為了少改出問題,往往要delay-delay-再delay。于是就陷入了一個我們寫的代碼越多,問題越多,delay也越嚴(yán)重的怪圈”
終于,在delay了28次后,我們爆發(fā)了,我們要它,對,就是它,單元測試!我們要寫單元測試!
于是乎,我們的開發(fā)流程變成了類似下面這個樣子:
多美好啊,開發(fā)效率高,交互質(zhì)量也高,大家有飯吃,大家都開心(測試:“我XXX”)。
“咳咳!干啥呢!干啥呢!意淫個毛線啊,這個版本發(fā)了嗎!看看覆蓋率才多少!”
好吧,回到現(xiàn)實(shí)。
??我們確實(shí)有開始寫單元測試,也有做一些努力,但遠(yuǎn)遠(yuǎn)不夠。我們針對相對穩(wěn)定的公共組件,做了30%-50%的覆蓋率,但是對上層相對復(fù)雜的業(yè)務(wù)邏輯幾乎為0。而容易出問題,需要經(jīng)常變更的,也恰恰是這些上層業(yè)務(wù)邏輯。這些業(yè)務(wù)代碼可能經(jīng)常變更,用例也需要隨之變更,維護(hù)成本相對更高(雖然寫了單元測試會降低維護(hù)成本,但這恰恰是多數(shù)開發(fā)者很難跨越的坎兒)。
IntelliTest
IntelliTest可以做什么?
IntelliTest通過探測你的.NET代碼,自動生成一組高覆蓋率的測試用例。雖然開發(fā)人員還是需要手動編寫單元測試,但是IntelliTest可以確保對代碼進(jìn)行了充分的測試。
中文都能看懂,操作呢?
??再回憶一下,我們是不是經(jīng)常遇到這樣的情況:為了覆蓋不同的分支語句,我們需要寫多個用例,然而這些用例中很多代碼都是一樣,每次都要做相同的arrange,相同的action,甚至相同的assert。對的,你可能會說,“NUnit已經(jīng)提供了解決這個問題的方法啊,而且超級簡單”,確實(shí),在NUnit中,我們可以這樣寫用例:
[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); }但是MSTest沒有這么簡單的方法啊,MSTest有的只是DataSource,而這又跟IntelliTest有什么關(guān)系呢?還真有那么點(diǎn)兒關(guān)系,MSTest雖然沒有提供多參數(shù)的用例支持,但是隨著IntelliTest的推出,提供了Parameterized Unit Tests[PUT](參數(shù)化單元測試),通過PUT,IntelliTest會自動為我們生成不同輸入?yún)?shù)的用例,而且保證每個用例都是有意義的。
??除此之外,IntelliTest能夠在你修改了業(yè)務(wù)代碼的情況下快速生成新的測試用例,大大減輕了測試用例的維護(hù)。同時這些測試用例都可以保存下來,供后續(xù)回歸測試使用。
一個具體的栗子
有如下代碼:
/// <summary> /// 判斷一個文件是否包含指定后綴 /// </summary> /// <param name="fileName"></param> /// <param name="suffix"></param> /// <returns></returns> public static bool IsSuffix(string fileName, string suffix) {var fileNameLower = fileName.ToLower();if (fileNameLower.EndsWith(suffix))return true;return false; }我們右擊它選擇運(yùn)行IntelliTest,接下來會彈出一個IntelliTest結(jié)果窗口,它是長下面這個樣子滴:
解釋一下各個名詞的意思:
- 塊(blocks):已覆蓋Block數(shù)/IntelliTest探測到的總Block數(shù)(Block是啥?)
- 斷言(asserts):PUT中運(yùn)行過的斷言數(shù)/PUT中定義的所有斷言數(shù)
- 運(yùn)行(runs):探測期間,IntelliTest嘗試運(yùn)行的次數(shù)
在運(yùn)行結(jié)果窗口中我們看到,IntelliTest為我們生成了9個用例,其中4個通過,5個失敗,并且給出了失敗原因。點(diǎn)擊每一條用例,在右側(cè)會有此用例更加詳細(xì)的信息(包括詳細(xì)的參數(shù)和調(diào)用堆棧),便于我們跟蹤分析錯誤原因。
??全選后保存,IntelliTest自動添加一個測試工程并將用例放到PUT文件下面的g.cs文件中,后續(xù)可以繼續(xù)利用這些用例做測試。實(shí)際上,微軟并不希望我們編輯g.cs文件,在每次運(yùn)行IntelliTest時,它會更新g.cs文件至最新。
??多次提到PUT,有必要鄭重介紹一下它了。所謂的“參數(shù)化單元測試”,指的是可以定義多組參數(shù)的單元測試方法。(哇,好鄭重啊!),是的,就是這么簡單直白。通過查看IntelliTest生成的文件很容易發(fā)現(xiàn),在g.cs中的每一個用例最終都是通過調(diào)用PUT來實(shí)現(xiàn)測試的,這就是IntelliTest的參數(shù)化。在 傳統(tǒng)單元測試 部分提到的NUnit的多參數(shù)測試就是NUnit的參數(shù)化單元測試,但是IntelliTest為我們實(shí)現(xiàn)了自動化。
??然而,現(xiàn)實(shí)總是比想象復(fù)雜,我們的業(yè)務(wù)代碼也遠(yuǎn)比栗子難嚼。在開發(fā)中使用IntelliTest會遇到的問題遠(yuǎn)比栗子中多,比如本篇未提到的IntelliTest結(jié)果窗口中的異常。IntelliTest的更多問題,下集繼續(xù)。
date: 2017-10-29 09:02:23
轉(zhuǎn)載于:https://www.cnblogs.com/erdao/p/8419765.html
總結(jié)
以上是生活随笔為你收集整理的IntelliTest实战直通车(上集)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么对开发者很重要?
- 下一篇: Scrapy爬虫-win7下创建运行项目