如何評估測試用例有效性
“
每一個測試人都經(jīng)歷過測試用例評審,但是如何評估測試用例的有效性呢??是不是我按照黑盒測試用例的設(shè)計原則來設(shè)計,這個測試用例就是一個有效的測試用例呢?(黑盒測試用例設(shè)計方法有:等價類劃分法、邊界值分析法、錯誤推測法、因果圖法、判定表驅(qū)動法、正交試驗設(shè)計法、功能圖法、場景圖法)。
我想答案是否定的,測試用例的有效性,更像是個玄學(xué),長期以來,并沒有一個相對科學(xué)的辦法來驗證。
下面這篇文章是原螞蟻金服-義理大佬的一些實踐,給我非常大啟發(fā),分享給大家。
”
01
—
為什么要評估測試用例有效性
想想你的團(tuán)隊有沒有碰見過這樣的問題:
1. 這么多的Case,花了大量時間和資源去運行,真的能發(fā)現(xiàn)Bug嗎?
2. CI做到90%的行覆蓋率了,能發(fā)現(xiàn)問題嗎?
3. 測試用例越來越多,刪除一些,會不會就發(fā)現(xiàn)不了問題了?
4. 怎么找出那些為了覆蓋而覆蓋,但是發(fā)現(xiàn)不了真正問題的測試用例?
想想上面的問題,再捫心自問:測試用例的有效性要不要評估?
測試用例有效性
要評估測試用例的有效性,首先要看,什么樣的測試用例是有效的?
測試用例有效性

那么,測試用例具備不具備有效性,主要看以下指標(biāo):
這個測試用例不僅能夠“觸發(fā)被測代碼的各種分支”,還能夠做好結(jié)果校驗。
當(dāng)業(yè)務(wù)代碼出現(xiàn)問題的時候,測試用例可以發(fā)現(xiàn)這個問題,我們就認(rèn)為這一組測試用例是有效的。
當(dāng)業(yè)務(wù)代碼出現(xiàn)問題的時候,測試用例沒能發(fā)現(xiàn)這個問題,我們就認(rèn)為這一組測試用例是無效的。
由此引出測試用例有效性的理論建模:
?測試有效性 = 被發(fā)現(xiàn)的問題數(shù) / 出現(xiàn)問題的總數(shù)。
02?
—
測試用例有效性評估度量方法
從運行時、非運行時, 正向和逆向這個維度, 我們可以得出以下的度量方式:

正向的鏈路掃描和靜態(tài)掃描都比較常見,這里重點介紹下逆向的方式:
代碼注入:
屬于非運行時度量方式。通過向代碼注入變異,來看測試用例是否能夠發(fā)現(xiàn)問題。
內(nèi)存注入:
屬于運行時度量方式。也叫“”故障注入“”, 指在運行時進(jìn)行操作和修改,來檢查你的測試用例是否能反映出這個問題。?常見的有對API調(diào)用的返回結(jié)果進(jìn)行修改,如果更改后,測試用例執(zhí)行報錯,則說明測試用例有效,反之說明無效。
這里重點講下代碼注入。
代碼注入的原理是變異測試(mutation testing)。

變異測試的例子
我們用了一組測試用例(3個),去測試一個判斷分支。
而為了證明這一組測試用例的有效性,我們向業(yè)務(wù)代碼中注入變異。我們把b<100的條件改成了b<=100。
我們認(rèn)為:一組Success的測試用例,在其被測對象發(fā)生變化后(注入變異后),應(yīng)該至少有一個失敗。如果這組測試用例仍然全部Success,則這組測試用例的有效性不足。
通過變異測試的方式:讓注入變異后的業(yè)務(wù)代碼作為“測試用例”,來測試“測試代碼”。
那么可選的變異有哪些呢?
1. 線上的故障總結(jié)。
根據(jù)線上出現(xiàn)過的故障,總結(jié)其故障模式,然后將歸納后的符合故障模式的代碼變異注入,以期望未來線上不會有同樣問題出現(xiàn)。比如,代碼中把空判斷刪除、更改日期格式(冬令時改成夏令時)、把相似函數(shù)混淆(例如把函數(shù)encodeing改成decoding)甚至發(fā)大程序中的數(shù)據(jù)范圍(把金額從放大10倍或100倍)來引發(fā)錯誤。
2. 解決未知的問題。
上面的部分是已知的問題,那么還有很多我不知道有哪些問題的問題,這些問題怎么解決呢?
對于此類問題,可以尋找其通用解。
例如基于Java語言,把它的運算符,代碼結(jié)構(gòu)這一類的約定俗成的編碼規(guī)范進(jìn)行修改,例如把+改成-, 把=改成!=。
在此基礎(chǔ)上,可以實現(xiàn)多種規(guī)則,主動的注入下面這些變異:

上面的介紹是理論,每個團(tuán)隊都可以看,可以學(xué)。下面的是螞蟻金服的實踐方案,大家可以按需參考
03
—
代碼注入工程化方案
為了全自動的進(jìn)行測試有效性評估,我們做了一個變異機器人,其主要運作是:
往被測代碼中寫入一個BUG(即:變異)
執(zhí)行測試
把測試結(jié)果和無變異時的測試結(jié)果做比對,判斷是否有新的用例失敗
重復(fù)1-3若干次,每次注入一個不同的Bug
統(tǒng)計該系統(tǒng)的“測試有效性”

變異機器人的優(yōu)點:
防錯上線:變異是單獨拉代碼分支,且該代碼分支永遠(yuǎn)不會上線,不影響生產(chǎn)。
全自動:只需要給出系統(tǒng)代碼的git地址,即可進(jìn)行評估,得到改進(jìn)報告。
高效:數(shù)小時即可完成一個系統(tǒng)的測試有效性評估。
擴(kuò)展性:該模式可以支持JAVA以及JAVA以外的多種語系。
適用性:該方法不僅適用于單元測試,還適用于其他自動化測試,例如接口測試、功能測試、集成測試。
變異機器人的使用門檻:
測試成功率:只會選擇通過率100%的測試用例,所對應(yīng)的業(yè)務(wù)代碼做變異注入。
測試覆蓋率:只會注入被測試代碼覆蓋的業(yè)務(wù)代碼,測試覆蓋率越高,評估越準(zhǔn)確。
檢查的結(jié)果如下:

04
—
?持續(xù)優(yōu)化
在執(zhí)行的過程中,會碰見如下的問題:

那么還有什么方式可以持續(xù)優(yōu)化呢?
<分鐘級的系統(tǒng)評估效率>
為了保證評估的準(zhǔn)確性,100個變異將會執(zhí)行全量用例100遍,每次執(zhí)行時間長是一大痛點。
高配版變異機器人給出的解法:
并行注入:基于代碼覆蓋率,識別UT之間的代碼覆蓋依賴關(guān)系,將獨立的變異合并到一次自動化測試中。
熱部署:基于字節(jié)碼做更新,減少變異和部署的過程。
精準(zhǔn)測試:基于UT代碼覆蓋信息,只運行和本次變異相關(guān)的UT(該方法不僅適用于UT,還適用于其他自動化測試,例如接口測試、功能測試、集成測試)
<學(xué)習(xí)型注入經(jīng)驗庫>
為了避免“殺蟲劑”效應(yīng),注入規(guī)則需要不斷的完善。
高配版變異機器人給出的解法:故障學(xué)習(xí),基于故障學(xué)習(xí)算法,不斷學(xué)習(xí)歷史的代碼BUG,并轉(zhuǎn)化為注入經(jīng)驗??蓪W(xué)習(xí)型經(jīng)驗庫目前覆蓋螞蟻金服的代碼庫,明年會覆蓋開源社區(qū)。
<兼容不穩(wěn)定環(huán)境>
集成測試環(huán)境會存在一定的不穩(wěn)定,難以判斷用例失敗是因為“發(fā)現(xiàn)了變異”還是“環(huán)境出了問題”,導(dǎo)致測試有效性評估存在誤差。
高配版變異機器人給出的解法:
高頻跑:同樣的變異跑10次,對多次結(jié)果進(jìn)行統(tǒng)計分析,減少環(huán)境問題引起的偶發(fā)性問題。
環(huán)境問題自動定位:接入附屬的日志服務(wù),它會基于用例日志/系統(tǒng)錯誤日志構(gòu)建的異常場景,自動學(xué)習(xí)“因環(huán)境問題導(dǎo)致的用例失敗”,準(zhǔn)確區(qū)分出用例是否發(fā)現(xiàn)變異。
05
—
最終我們要實現(xiàn)這樣的目標(biāo):
測試從 代碼都能跑-->代碼都被測試到了-->代碼都測試好了。

最后放一個測試度量三板斧:

如果大家對本演講的原視頻感興趣,可以通過此觀看:
https://www.itdks.com/Course/detail?id=117569
