高效測(cè)試用例組織算法pairwise之Python實(shí)現(xiàn)方法
開(kāi)篇:
測(cè)試過(guò)程中,對(duì)于多參數(shù)參數(shù)多值的情況進(jìn)行測(cè)試用例組織,之前一直使用【正交分析法】進(jìn)行用例組織,說(shuō)白了就是把每個(gè)參數(shù)的所有值分別和其他參數(shù)的值做一個(gè)全量組合,用Python腳本實(shí)現(xiàn),就是itertools模塊中product方法(又稱笛卡爾積法)。
正交分析法的優(yōu)點(diǎn)是測(cè)試用例覆蓋率100%,缺點(diǎn)測(cè)試用例數(shù)量龐大,執(zhí)行用例消耗的人工巨大。
Pairwise (結(jié)對(duì))算法源于對(duì)傳統(tǒng)的正交分析方法優(yōu)化后得到的產(chǎn)物,它的理論來(lái)自于數(shù)學(xué)統(tǒng)計(jì)。毫不避諱的說(shuō),本人看不懂?dāng)?shù)學(xué)統(tǒng)計(jì)中的學(xué)術(shù)論文,只能從網(wǎng)上找一些通俗簡(jiǎn)單的說(shuō)法來(lái)理解其基本含義。
網(wǎng)上很多人都實(shí)例都是用 【操作系統(tǒng),瀏覽器,語(yǔ)言環(huán)境】來(lái)舉例的,本人也做同樣示例:
操作系統(tǒng): W(Windows),L(Linux),Mac (Mac) ;瀏覽器:M(Firefox),O(Opera),IE;語(yǔ)言環(huán)境:C(中文),E(英文)
按照正交分析法:會(huì)產(chǎn)生3x3x2=18種組合方式 ,測(cè)試用例覆蓋率100%。
Pairwise結(jié)對(duì)測(cè)試用例組織法,可壓縮到9種組合方式。因此有點(diǎn)是 測(cè)試用例數(shù)量少,缺點(diǎn)是一定會(huì)有漏測(cè)。
引論:
Pairwise算法的核心理念
1、一組測(cè)試用例(每個(gè)用例有3個(gè)參數(shù)的值組成,如[W,M,C])中每一個(gè)2個(gè)元素組合起來(lái),兩兩組合,就有3種組合方式(有位置的[W,M][W,C][M,C]);
2、如果這第一組測(cè)試用兩兩組合出的3種組合方式,對(duì)比原則:[W,M]只會(huì)和其他組的第一個(gè)元素對(duì)比,[W,C]只會(huì)和其他組中第二個(gè)元素對(duì)比。。。。;
[W,M][W,C][M,C]這三個(gè)元素分別出現(xiàn)在其余有效組位置相同的元素中,就可以認(rèn)為這一組Case為多余Case,并進(jìn)行刪除。
名詞解釋:【有效組】表示未被刪除的組和未被對(duì)比過(guò)的組。舉例:第1,3組被刪除,則第4組要對(duì)比的有效組為第2,5,6,7...18組。有效組這里踩過(guò)坑%>_<%
3、最終得到測(cè)試用例,就是結(jié)對(duì)算法計(jì)算出來(lái)的最優(yōu)測(cè)試用例集合。
牛逼閃閃的學(xué)術(shù)證明
Pairwise是L. L. Thurstone(29 May1887 – 30 September 1955)在1927年首先提出來(lái)的。他是美國(guó)的一位心理統(tǒng)計(jì)學(xué)家。Pairwise也正是基于數(shù)學(xué)統(tǒng)計(jì)和對(duì)傳統(tǒng)的正交分析法進(jìn)行優(yōu)化后得到的產(chǎn)物。
Pairwise基于如下2個(gè)假設(shè):
(1)每一個(gè)維度都是正交的,即每一個(gè)維度互相都沒(méi)有交集。
(2)根據(jù)數(shù)學(xué)統(tǒng)計(jì)分析,73%的缺陷(單因子是35%,雙因子是38%)是由單因子或2個(gè)因子相互作用產(chǎn)生的。19%的缺陷是由3個(gè)因子相互作用產(chǎn)生的。
因此,pairwise基于覆蓋所有2因子的交互作用產(chǎn)生的用例集合性價(jià)比最高而產(chǎn)生的。
正文
一、思路
對(duì)一個(gè)測(cè)試場(chǎng)景如何從何從輸入被測(cè)條件,到產(chǎn)出Pairwise測(cè)試用例,使用Python編程思路如下:
1、將allparams=[['M','O','P'],['W','L','I'],['C','E']]進(jìn)行笛卡爾積全組合處理,生成正則分析法產(chǎn)生的全量測(cè)試用例集合的一維數(shù)組(len=N);
2、將全量測(cè)試用例中的每個(gè)測(cè)試用例,都進(jìn)行兩兩組合的分解處理,生成與全量測(cè)試用例集合 長(zhǎng)度相同的二維數(shù)組(一維 len=N);
3、使用Python版Pairwise算法剔除無(wú)效測(cè)試用例,最終得到有效的結(jié)對(duì)測(cè)試用例集合;
代碼第1,2函數(shù)利用Python自帶數(shù)學(xué)計(jì)算庫(kù)itertools編寫,代碼第3函數(shù)為本人死磕出來(lái)的代碼。
二、直接上代碼
# -*- coding: utf-8 -*- from datetime import * import random,os,copy,time import logging import itertools ''' #Author:Kuzaman #Time:2017-07-18 ''' class utils2 : #1、笛卡爾積 對(duì)參數(shù)分組全排列 def product(self,tuple1): newlist=[] for x in eval('itertools.product'+str(tuple(tuple1))): newlist.append(x) return newlist #2、對(duì)笛卡爾積處理后的二維原始數(shù)據(jù)進(jìn)行N配對(duì)處理,得到Pairwise計(jì)算之前的數(shù)據(jù) def get_pairslist(self,lista): pwlist = [] for i in lista: subtemplist = [] for sublista in itertools.combinations(i, 2): subtemplist.append(sublista) pwlist.append(subtemplist) return pwlist #3、進(jìn)行Pirwise算法計(jì)算 def pairwise(self,listb): sublistlen = len(listb[1]) flag = [0]*sublistlen templistb = copy.deepcopy(listb) delmenu = [] holdmenu=[] self.pprint (listb) print ('--'*25) for lb in listb: for sublb in lb: for k in templistb: Xa = lb.index(sublb) Ya = listb.index(lb) if k != lb and sublb == k[Xa]: # print (sublb,'===>' ,k[Xa],'相等了。。。') flag[Xa] = 1 break else: # print (sublb,'===>' ,k[Xa],'不不不等了。。。') flag[Xa] = 0 # print ('下標(biāo)%d,子元素 %s 雙匹配對(duì)比結(jié)果flag:%s'%(listb.index(lb),lb,flag)) if 0 not in flag: num = listb.index(lb) delmenu.append(num) templistb.remove(lb) # print ('下標(biāo)為%d行應(yīng)刪除,內(nèi)容=%s,'%(num,lb)) # print ('delmenu:',delmenu) else: num2 = listb.index(lb) holdmenu.append(num2) # print ('下標(biāo)為%d行應(yīng)保留,內(nèi)容=%s,'%(num2,lb)) # print('holdmenu=',holdmenu) # print ('***'*20) print ('保留元素列表:%s \n匹配重復(fù)元素列表:%s'%(holdmenu,delmenu)) return templistb def pwresult(self,slist,delmenu): for x in delmenu: slist.remove(slist[x]) return slist def pprint(self,list): for i in list: print ('line %d:'%(list.index(i)+1),i) if __name__ == '__main__': u2 = utils2() allparams=[['M','O','P'],['W','L','I'],['C','E']]#,'K'],[1,2,3],['Yes','No']] str = u2.product(allparams) strpc = u2.get_pairslist(str) finallist = u2.pairwise(strpc) print('最終保留測(cè)試用例個(gè)數(shù):%d 個(gè)'%(len(finallist))) u2.pprint(finallist)
代碼解讀:
第三for循環(huán)代碼39~48行,主要是垂直判斷 待檢測(cè)元素 與 相同位置的元素是否有相同的
第二for循環(huán)代碼38~48行,把一組測(cè)試用例中的兩兩配對(duì),從左至右分別和同位置的元素作對(duì)比
第一for循環(huán)代碼37~48行,遍歷每一組測(cè)試用例。
第50~58行代碼,判斷一組用例的兩兩配對(duì)在其他組同位置上從上到下都能找到相同元素,則將改無(wú)效Case從templistb中刪除,保持templistb的有效性。
執(zhí)行結(jié)果:
line 1: [('M', 'W'), ('M', 'C'), ('W', 'C')] <---第二個(gè)函數(shù)get_pairslist(self,lista)處理后的兩兩配對(duì)組合 line 2: [('M', 'W'), ('M', 'E'), ('W', 'E')] <---同第一行解釋 line 3: [('M', 'L'), ('M', 'C'), ('L', 'C')] line 4: [('M', 'L'), ('M', 'E'), ('L', 'E')] line 5: [('M', 'I'), ('M', 'C'), ('I', 'C')] line 6: [('M', 'I'), ('M', 'E'), ('I', 'E')] line 7: [('O', 'W'), ('O', 'C'), ('W', 'C')] line 8: [('O', 'W'), ('O', 'E'), ('W', 'E')] line 9: [('O', 'L'), ('O', 'C'), ('L', 'C')] line 10: [('O', 'L'), ('O', 'E'), ('L', 'E')] line 11: [('O', 'I'), ('O', 'C'), ('I', 'C')] line 12: [('O', 'I'), ('O', 'E'), ('I', 'E')] line 13: [('P', 'W'), ('P', 'C'), ('W', 'C')] line 14: [('P', 'W'), ('P', 'E'), ('W', 'E')] line 15: [('P', 'L'), ('P', 'C'), ('L', 'C')] line 16: [('P', 'L'), ('P', 'E'), ('L', 'E')] line 17: [('P', 'I'), ('P', 'C'), ('I', 'C')] line 18: [('P', 'I'), ('P', 'E'), ('I', 'E')] <----同第一行解釋 -------------------------------------------------- 保留元素列表:[1, 3, 4, 7, 9, 10, 12, 14, 17] <----有效用例在數(shù)組中下標(biāo) 匹配重復(fù)元素列表:[0, 2, 5, 6, 8, 11, 13, 15, 16] <----被剔除的無(wú)效測(cè)試用例在數(shù)組中下標(biāo) 最終保留測(cè)試用例個(gè)數(shù):9 個(gè) line 1: [('M', 'W'), ('M', 'E'), ('W', 'E')] line 2: [('M', 'L'), ('M', 'E'), ('L', 'E')] line 3: [('M', 'I'), ('M', 'C'), ('I', 'C')] line 4: [('O', 'W'), ('O', 'E'), ('W', 'E')] line 5: [('O', 'L'), ('O', 'E'), ('L', 'E')] line 6: [('O', 'I'), ('O', 'C'), ('I', 'C')] line 7: [('P', 'W'), ('P', 'C'), ('W', 'C')] line 8: [('P', 'L'), ('P', 'C'), ('L', 'C')] line 9: [('P', 'I'), ('P', 'E'), ('I', 'E')] [Finished in 0.2s]
三、代碼核心內(nèi)容白話解釋
pairwise(self,listb)函數(shù)包含3層for循環(huán),先畫一個(gè)二維數(shù)組:
i[0] i[1] i[2] listb.index(i)=0 : [('M', 'W'), ('M', 'C'), ('W', 'C')] listb.index(i)=1 : [('M', 'W'), ('M', 'E'), ('W', 'E')] listb.index(i) : [('M', 'L'), ('M', 'C'), ('L', 'C')] listb.index(i) : [('M', 'L'), ('M', 'E'), ('L', 'E')] listb.index(i) : [('M', 'I'), ('M', 'C'), ('I', 'C')] listb.index(i) : [('M', 'I'), ('M', 'E'), ('I', 'E')] listb.index(i) : [('O', 'W'), ('O', 'E'), ('W', 'E')] listb.index(i) : [('O', 'L'), ('O', 'C'), ('L', 'C')] listb.index(i) : [('O', 'L'), ('O', 'E'), ('L', 'E')] listb.index(i) : [('O', 'I'), ('O', 'C'), ('I', 'C')] listb.index(i)=n : [('O', 'I'), ('O', 'E'), ('I', 'E')]
二維列表 listb ,其中的行(發(fā)音:hang,二聲。橫著的那排)從上到下就是第一層for循環(huán) ;每一行中的i[0],i[1],i[2]就是第二層for循環(huán)從左至右;第三次for循環(huán)元素i[x]從上之下與有效組 templistb通位置元素的對(duì)比。
1、第n行的i[0]要和有效templistb的其他行的i[0]元素對(duì)比(第三for),如果有相等的,記錄一個(gè)標(biāo)識(shí) 如 flag1=True,如果沒(méi)有相等的記錄falg1=False;
2、直到第二for中的i[0],i[1],i[2]都進(jìn)行對(duì)比后,會(huì)得到 [flag1,flag2,flag3 ],所有flag=True則該行為無(wú)效用例
3、第一for遍歷全部組合,最終得到保留下來(lái)的有效templistb
見(jiàn)圖:
完結(jié)篇
以上是自己編寫的pairwise的全部?jī)?nèi)容,此算法共耗時(shí)3天:
第一天在確定這究竟是什么算法,看了很多學(xué)術(shù)文獻(xiàn),看不懂;
第二天開(kāi)始寫程序,for的嵌套循環(huán)設(shè)計(jì)耽誤很久;
第三天程序成型,有執(zhí)行結(jié)果,發(fā)現(xiàn)與參考文章結(jié)論不同,隨后再仔細(xì)研讀參考文章,發(fā)現(xiàn)掉坑里了。重新推翻代碼按照正確思路,用1個(gè)小時(shí)完成最終結(jié)果。
本人做測(cè)試的,還不是專業(yè)的測(cè)試開(kāi)發(fā),寫代碼比較費(fèi)勁,真正應(yīng)了設(shè)計(jì)占70%,編碼占30%的理。如果像基礎(chǔ)在差點(diǎn),邏輯在亂點(diǎn),就只能用時(shí)間堆了。
希望對(duì)需要組織測(cè)試用例,或者自動(dòng)化測(cè)試中需要組織用例的同行們有所幫助。
這篇高效測(cè)試用例組織算法pairwise之Python實(shí)現(xiàn)方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python存儲(chǔ)List數(shù)據(jù)到文件(text/csv/excel)幾種常見(jiàn)方法
在數(shù)據(jù)分析中經(jīng)常需要從csv格式的文件中存取數(shù)據(jù)以及將數(shù)據(jù)寫書到csv文件中,下面這篇文章主要給大家介紹了關(guān)于Python存儲(chǔ)List數(shù)據(jù)到文件(text/csv/excel)的幾種常見(jiàn)方法,需要的朋友可以參考下2024-02-02pytest使用parametrize將參數(shù)化變量傳遞到fixture
這篇文章主要為大家介紹了pytest使用parametrize將參數(shù)化變量傳遞到fixture的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05使用anaconda的pip安裝第三方python包的操作步驟
今天小編就為大家分享一篇使用anaconda的pip安裝第三方python包的操作步驟,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06Python利用正則表達(dá)式匹配并截取指定子串及去重的方法
這篇文章主要介紹了Python利用正則表達(dá)式匹配并截取指定子串及去重的方法,涉及Python正則表達(dá)式匹配及字符串截取操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07