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

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

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

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

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

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

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

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

最后放一個(gè)測試度量三板斧:

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