IntelliTest實(shí)戰(zhàn)直通車(上集)

IntelliTest前世今生

??IntelliTest的前身是微軟研究院的白盒測(cè)試框架Pex,當(dāng)時(shí)的Pex并未集成到Visual Studio中,開(kāi)發(fā)者需要單獨(dú)下載和配置,在下載時(shí)會(huì)附帶一個(gè)叫Moles的隔離框架(它更早些的名字叫Stubs)。隨著Visual Studio 2015 RC 版本的發(fā)布,Pex集成到Visual Studio中,成了IntelliTest,而Moles也升級(jí)成了Microsoft Fakes。

傳統(tǒng)單元測(cè)試

??回憶一下,寫單元測(cè)試之前,我們的開(kāi)發(fā)流程一般是怎樣一個(gè)過(guò)程。
“我們很忙,一直忙著開(kāi)發(fā)開(kāi)發(fā),眼看就要到deadline了,加緊繼續(xù)開(kāi)發(fā)開(kāi)發(fā)。在這種情況下的產(chǎn)品質(zhì)量可想而知,于是耐心的測(cè)試給我們報(bào)bug,善良的用戶給我們提意見(jiàn),沒(méi)辦法,要吃飯啊,我們又去改代碼,然而代碼并不是你想改,想改就能改的啊,為了少改出問(wèn)題,往往要delay-delay-再delay。于是就陷入了一個(gè)我們寫的代碼越多,問(wèn)題越多,delay也越嚴(yán)重的怪圈”


image.png

終于,在delay了28次后,我們爆發(fā)了,我們要它,對(duì),就是它,單元測(cè)試!我們要寫單元測(cè)試!

于是乎,我們的開(kāi)發(fā)流程變成了類似下面這個(gè)樣子:


image.png

多美好啊,開(kāi)發(fā)效率高,交互質(zhì)量也高,大家有飯吃,大家都開(kāi)心(測(cè)試:“我XXX”)。

“咳咳!干啥呢!干啥呢!意淫個(gè)毛線啊,這個(gè)版本發(fā)了嗎!看看覆蓋率才多少!”

好吧,回到現(xiàn)實(shí)。

??我們確實(shí)有開(kāi)始寫單元測(cè)試,也有做一些努力,但遠(yuǎn)遠(yuǎn)不夠。我們針對(duì)相對(duì)穩(wěn)定的公共組件,做了30%-50%的覆蓋率,但是對(duì)上層相對(duì)復(fù)雜的業(yè)務(wù)邏輯幾乎為0。而容易出問(wèn)題,需要經(jīng)常變更的,也恰恰是這些上層業(yè)務(wù)邏輯。這些業(yè)務(wù)代碼可能經(jīng)常變更,用例也需要隨之變更,維護(hù)成本相對(duì)更高(雖然寫了單元測(cè)試會(huì)降低維護(hù)成本,但這恰恰是多數(shù)開(kāi)發(fā)者很難跨越的坎兒)。

IntelliTest

IntelliTest可以做什么?

IntelliTest通過(guò)探測(cè)你的.NET代碼,自動(dòng)生成一組高覆蓋率的測(cè)試用例。雖然開(kāi)發(fā)人員還是需要手動(dòng)編寫單元測(cè)試,但是IntelliTest可以確保對(duì)代碼進(jìn)行了充分的測(cè)試。

中文都能看懂,操作呢?

??再回憶一下,我們是不是經(jīng)常遇到這樣的情況:為了覆蓋不同的分支語(yǔ)句,我們需要寫多個(gè)用例,然而這些用例中很多代碼都是一樣,每次都要做相同的arrange,相同的action,甚至相同的assert。對(duì)的,你可能會(huì)說(shuō),“NUnit已經(jīng)提供了解決這個(gè)問(wèn)題的方法啊,而且超級(jí)簡(jiǎn)單”,確實(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沒(méi)有這么簡(jiǎn)單的方法啊,MSTest有的只是DataSource,而這又跟IntelliTest有什么關(guān)系呢?還真有那么點(diǎn)兒關(guān)系,MSTest雖然沒(méi)有提供多參數(shù)的用例支持,但是隨著IntelliTest的推出,提供了Parameterized Unit Tests[PUT](參數(shù)化單元測(cè)試),通過(guò)PUT,IntelliTest會(huì)自動(dòng)為我們生成不同輸入?yún)?shù)的用例,而且保證每個(gè)用例都是有意義的。

??除此之外,IntelliTest能夠在你修改了業(yè)務(wù)代碼的情況下快速生成新的測(cè)試用例,大大減輕了測(cè)試用例的維護(hù)。同時(shí)這些測(cè)試用例都可以保存下來(lái),供后續(xù)回歸測(cè)試使用。

一個(gè)具體的栗子

有如下代碼:

/// <summary>
/// 判斷一個(gè)文件是否包含指定后綴
/// </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,接下來(lái)會(huì)彈出一個(gè)IntelliTest結(jié)果窗口,它是長(zhǎng)下面這個(gè)樣子滴:

image.png

解釋一下各個(gè)名詞的意思:

  • 塊(blocks):已覆蓋Block數(shù)/IntelliTest探測(cè)到的總Block數(shù)(Block是啥?
  • 斷言(asserts):PUT中運(yùn)行過(guò)的斷言數(shù)/PUT中定義的所有斷言數(shù)
  • 運(yùn)行(runs):探測(cè)期間,IntelliTest嘗試運(yùn)行的次數(shù)

在運(yùn)行結(jié)果窗口中我們看到,IntelliTest為我們生成了9個(gè)用例,其中4個(gè)通過(guò),5個(gè)失敗,并且給出了失敗原因。點(diǎn)擊每一條用例,在右側(cè)會(huì)有此用例更加詳細(xì)的信息(包括詳細(xì)的參數(shù)和調(diào)用堆棧),便于我們跟蹤分析錯(cuò)誤原因。

??全選后保存,IntelliTest自動(dòng)添加一個(gè)測(cè)試工程并將用例放到PUT文件下面的g.cs文件中,后續(xù)可以繼續(xù)利用這些用例做測(cè)試。實(shí)際上,微軟并不希望我們編輯g.cs文件,在每次運(yùn)行IntelliTest時(shí),它會(huì)更新g.cs文件至最新。

??多次提到PUT,有必要鄭重介紹一下它了。所謂的“參數(shù)化單元測(cè)試”,指的是可以定義多組參數(shù)的單元測(cè)試方法。(哇,好鄭重啊?。?,是的,就是這么簡(jiǎn)單直白。通過(guò)查看IntelliTest生成的文件很容易發(fā)現(xiàn),在g.cs中的每一個(gè)用例最終都是通過(guò)調(diào)用PUT來(lái)實(shí)現(xiàn)測(cè)試的,這就是IntelliTest的參數(shù)化。在 傳統(tǒng)單元測(cè)試 部分提到的NUnit的多參數(shù)測(cè)試就是NUnit的參數(shù)化單元測(cè)試,但是IntelliTest為我們實(shí)現(xiàn)了自動(dòng)化。

??然而,現(xiàn)實(shí)總是比想象復(fù)雜,我們的業(yè)務(wù)代碼也遠(yuǎn)比栗子難嚼。在開(kāi)發(fā)中使用IntelliTest會(huì)遇到的問(wèn)題遠(yuǎn)比栗子中多,比如本篇未提到的IntelliTest結(jié)果窗口中的異常。IntelliTest的更多問(wèn)題,下集繼續(xù)。



2017-10-29 09:02:23

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,694評(píng)論 19 139
  • 文章來(lái)自:http://blog.csdn.net/mj813/article/details/52451355 ...
    好大一只鵬閱讀 9,374評(píng)論 2 126
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評(píng)論 25 708
  • 春生夏長(zhǎng),秋收冬藏。芊兒跟著昭玉的節(jié)奏,把四季過(guò)成了詩(shī)意的生活。 雖然養(yǎng)兒不易,但昭玉并沒(méi)打算束縛芊兒的天性,她知...
    小主正紅閱讀 425評(píng)論 1 2
  • 這是我知乎的一句話介紹,但初心又是什么呢,不知道自己若干年后還能否記得。 記得小時(shí)候很天真,媽媽問(wèn)以后我以后想要做...
    Soccory閱讀 628評(píng)論 0 0

友情鏈接更多精彩內(nèi)容