Python如何實作組織演算法pairwise(高效測試用例)

黄舟
發布: 2017-07-20 15:37:18
原創
2717 人瀏覽過

下面小編就為大家帶來一篇高效測試用例組織演算法pairwise之Python實作方法。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧

開篇:

測試過程中,對於多參數參數多值的情況進行測試案例組織,之前一直使用【正交分析法】進行用例組織,說白了就是把每個參數的所有值分別和其他參數的值做一個全量組合,用Python腳本實現,就是itertools模組中product方法(又稱笛卡爾積法)。

正交分析法的優點是測試案例覆蓋率100%,缺點測試用例數量龐大,執行用例消耗的人工巨大。

Pairwise (配對)演算法源自於傳統的正交分析方法最佳化後所得到的產物,它的理論來自於數學統計。毫不避諱的說,本人看不懂數學統計中的學術論文,只能從網路上找一些通俗簡單的說法來理解其基本意義。

網路上很多人都實例都是用【作業系統,瀏覽器,語言環境】來舉例的,本人也做同樣範例:

作業系統: W(Windows),L( Linux),Mac (Mac) ;瀏覽器:M(Firefox),O(Opera),IE;語言環境:C(中文),E(英文)

依照正交分析法:會產生3x3x2 =18種組合方式,測試案​​例覆蓋率100%。

Pairwise結對測試案例組織法,可壓縮到9種組合方式。因此有點是 測試用例數量少,缺點是一定會有漏測。

引論:

#Pairwise演算法的核心概念

1.一組測試案例(每個用例有3個參數的值組成,如[W,M,C])中每一個2個元素組合起來,兩兩組合,就有3種組合方式(有位置的[W,M][W,C][M,C]);

2、如果這第一組測試用兩兩組合出的3種組合方式,對比原則:[W,M]只會和其他組的第一個元素對比,[W,C]只會和其他組中第二個元素對比。 。 。 。 ;

[W,M][W,C][M,C]這三個元素分別出現在其餘有效組位置相同的元素中,就可以認為這一組Case為多餘Case,並進行刪除。

名詞解釋:【有效組】表示未被刪除的組和未對比過的組。舉例:第1,3組刪除,則第4組要比較的有效組為第2,5,6,7...18組。有效組這裡踩過坑%>_<%

3、最終得到測試用例,就是結對演算法計算出來的最優測試用例集合。

牛逼閃閃的學術證明 

Pairwise是L. L. Thurstone(29 May1887 – 30 September 1955)在1927年首先提出來的。他是美國的一位心理統計學家。 Pairwise也正是基於數學統計和對傳統正交分析法的最佳化後所得到的產物。

Pairwise基於如下2個假設:

(1)每一個維度都是正交的,即每一個維度互相都沒有交集。

(2)根據數學統計分析,73%的缺陷(單因子是35%,雙因子是38%)是由單因子或2個因子交互作用產生的。 19%的缺陷是由3個因子交互作用產生的。

因此,pairwise是基於覆蓋所有2因子的交互作用所產生的用例集合性價比最高而產生的。

正文

一、想法

對測試場景如何從何從輸入被測條件,到產出Pairwise測試案例,使用Python程式設計想法如下:

1、將allparams=[['M','O','P'],[' W','L','I'],['C','E']]進行笛卡爾積全組合處理,產生正規分析法產生的全量測試案例集合的一維數組(len=N);

2、將全量測試案例中的每個測試案例,都進行兩兩組合的分解處理,產生與全量測試用例集合長度相同的二維數組(一維len=N);

3、使用Python版Pairwise演算法剔除無效測試案例,最終得到有效的結對測試用例集合;

程式碼第1,2函數利用Python自帶數學計算庫itertools編寫,程式碼第3函數為本人死磕出來的程式碼。

二、直接上程式碼


#
# -*- coding: utf-8 -*-
from datetime import *
import random,os,copy,time
import logging
import itertools
&#39;&#39;&#39;
#Author:Kuzaman
#Time:2017-07-18
&#39;&#39;&#39;
class utils2 :
 #1、笛卡尔积 对参数分组全排列
 def product(self,tuple1):
  newlist=[]
  for x in eval(&#39;itertools.product&#39;+str(tuple(tuple1))):
   newlist.append(x)
  return newlist 
 
 #2、对笛卡尔积处理后的二维原始数据进行N配对处理,得到Pairwise计算之前的数据
 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、进行Pirwise算法计算
 def pairwise(self,listb):
  sublistlen = len(listb[1])
  flag = [0]*sublistlen
  templistb = copy.deepcopy(listb)
  delmenu = []
  holdmenu=[]
  self.pprint (listb)
  print (&#39;--&#39;*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,&#39;===>&#39; ,k[Xa],&#39;相等了。。。&#39;)
      flag[Xa] = 1
      break
     else:
      # print (sublb,&#39;===>&#39; ,k[Xa],&#39;不不不等了。。。&#39;)
      flag[Xa] = 0
   # print (&#39;下标%d,子元素 %s 双匹配对比结果flag:%s&#39;%(listb.index(lb),lb,flag))
   if 0 not in flag:
    num = listb.index(lb)
    delmenu.append(num)
    templistb.remove(lb)
    # print (&#39;下标为%d行应删除,内容=%s,&#39;%(num,lb))
    # print (&#39;delmenu:&#39;,delmenu)
   else:
    num2 = listb.index(lb)
    holdmenu.append(num2)
    # print (&#39;下标为%d行应保留,内容=%s,&#39;%(num2,lb))
    # print(&#39;holdmenu=&#39;,holdmenu)
   # print (&#39;***&#39;*20)
  print (&#39;保留元素列表:%s \n匹配重复元素列表:%s&#39;%(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 (&#39;line %d:&#39;%(list.index(i)+1),i)  

if __name__ == &#39;__main__&#39;:
 u2 = utils2()
 allparams=[[&#39;M&#39;,&#39;O&#39;,&#39;P&#39;],[&#39;W&#39;,&#39;L&#39;,&#39;I&#39;],[&#39;C&#39;,&#39;E&#39;]]#,&#39;K&#39;],[1,2,3],[&#39;Yes&#39;,&#39;No&#39;]]
 str = u2.product(allparams)
 strpc = u2.get_pairslist(str)
 finallist = u2.pairwise(strpc)
 print(&#39;最终保留测试用例个数:%d 个&#39;%(len(finallist)))
 u2.pprint(finallist)
登入後複製

程式碼解讀:

第三for迴圈程式碼39~48行,主要是垂直判斷待偵測元素與相同位置的元素是否有相同的

第二for迴圈程式碼38~48行,把一組測試案例中的兩兩配對,從左到右分別和同位置的元素作對比

第一for迴圈程式碼37~48行,遍歷每一組測試案例。

第50~58行代码,判断一组用例的两两配对在其他组同位置上从上到下都能找到相同元素,则将改无效Case从templistb中删除,保持templistb的有效性。

执行结果:


line 1: [(&#39;M&#39;, &#39;W&#39;), (&#39;M&#39;, &#39;C&#39;), (&#39;W&#39;, &#39;C&#39;)]  <---第二个函数get_pairslist(self,lista)处理后的两两配对组合
line 2: [(&#39;M&#39;, &#39;W&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;W&#39;, &#39;E&#39;)]  <---同第一行解释
line 3: [(&#39;M&#39;, &#39;L&#39;), (&#39;M&#39;, &#39;C&#39;), (&#39;L&#39;, &#39;C&#39;)]
line 4: [(&#39;M&#39;, &#39;L&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;L&#39;, &#39;E&#39;)]
line 5: [(&#39;M&#39;, &#39;I&#39;), (&#39;M&#39;, &#39;C&#39;), (&#39;I&#39;, &#39;C&#39;)]
line 6: [(&#39;M&#39;, &#39;I&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;I&#39;, &#39;E&#39;)]
line 7: [(&#39;O&#39;, &#39;W&#39;), (&#39;O&#39;, &#39;C&#39;), (&#39;W&#39;, &#39;C&#39;)]
line 8: [(&#39;O&#39;, &#39;W&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;W&#39;, &#39;E&#39;)]
line 9: [(&#39;O&#39;, &#39;L&#39;), (&#39;O&#39;, &#39;C&#39;), (&#39;L&#39;, &#39;C&#39;)]
line 10: [(&#39;O&#39;, &#39;L&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;L&#39;, &#39;E&#39;)]
line 11: [(&#39;O&#39;, &#39;I&#39;), (&#39;O&#39;, &#39;C&#39;), (&#39;I&#39;, &#39;C&#39;)]
line 12: [(&#39;O&#39;, &#39;I&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;I&#39;, &#39;E&#39;)]
line 13: [(&#39;P&#39;, &#39;W&#39;), (&#39;P&#39;, &#39;C&#39;), (&#39;W&#39;, &#39;C&#39;)]
line 14: [(&#39;P&#39;, &#39;W&#39;), (&#39;P&#39;, &#39;E&#39;), (&#39;W&#39;, &#39;E&#39;)]
line 15: [(&#39;P&#39;, &#39;L&#39;), (&#39;P&#39;, &#39;C&#39;), (&#39;L&#39;, &#39;C&#39;)]
line 16: [(&#39;P&#39;, &#39;L&#39;), (&#39;P&#39;, &#39;E&#39;), (&#39;L&#39;, &#39;E&#39;)]
line 17: [(&#39;P&#39;, &#39;I&#39;), (&#39;P&#39;, &#39;C&#39;), (&#39;I&#39;, &#39;C&#39;)]
line 18: [(&#39;P&#39;, &#39;I&#39;), (&#39;P&#39;, &#39;E&#39;), (&#39;I&#39;, &#39;E&#39;)]  <----同第一行解释
--------------------------------------------------
保留元素列表:[1, 3, 4, 7, 9, 10, 12, 14, 17]  <----有效用例在数组中下标
匹配重复元素列表:[0, 2, 5, 6, 8, 11, 13, 15, 16]  <----被剔除的无效测试用例在数组中下标
最终保留测试用例个数:9 个
line 1: [(&#39;M&#39;, &#39;W&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;W&#39;, &#39;E&#39;)]
line 2: [(&#39;M&#39;, &#39;L&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;L&#39;, &#39;E&#39;)]
line 3: [(&#39;M&#39;, &#39;I&#39;), (&#39;M&#39;, &#39;C&#39;), (&#39;I&#39;, &#39;C&#39;)]
line 4: [(&#39;O&#39;, &#39;W&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;W&#39;, &#39;E&#39;)]
line 5: [(&#39;O&#39;, &#39;L&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;L&#39;, &#39;E&#39;)]
line 6: [(&#39;O&#39;, &#39;I&#39;), (&#39;O&#39;, &#39;C&#39;), (&#39;I&#39;, &#39;C&#39;)]
line 7: [(&#39;P&#39;, &#39;W&#39;), (&#39;P&#39;, &#39;C&#39;), (&#39;W&#39;, &#39;C&#39;)]
line 8: [(&#39;P&#39;, &#39;L&#39;), (&#39;P&#39;, &#39;C&#39;), (&#39;L&#39;, &#39;C&#39;)]
line 9: [(&#39;P&#39;, &#39;I&#39;), (&#39;P&#39;, &#39;E&#39;), (&#39;I&#39;, &#39;E&#39;)]
[Finished in 0.2s]
登入後複製

三、代码核心内容白话解释

pairwise(self,listb)函数包含3层for循环,先画一个二维数组:


i[0]  i[1]  i[2]
listb.index(i)=0 : [(&#39;M&#39;, &#39;W&#39;), (&#39;M&#39;, &#39;C&#39;), (&#39;W&#39;, &#39;C&#39;)]
listb.index(i)=1 : [(&#39;M&#39;, &#39;W&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;W&#39;, &#39;E&#39;)]
listb.index(i) : [(&#39;M&#39;, &#39;L&#39;), (&#39;M&#39;, &#39;C&#39;), (&#39;L&#39;, &#39;C&#39;)]
listb.index(i) : [(&#39;M&#39;, &#39;L&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;L&#39;, &#39;E&#39;)]
listb.index(i) : [(&#39;M&#39;, &#39;I&#39;), (&#39;M&#39;, &#39;C&#39;), (&#39;I&#39;, &#39;C&#39;)]
listb.index(i) : [(&#39;M&#39;, &#39;I&#39;), (&#39;M&#39;, &#39;E&#39;), (&#39;I&#39;, &#39;E&#39;)]
listb.index(i) : [(&#39;O&#39;, &#39;W&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;W&#39;, &#39;E&#39;)]
listb.index(i) : [(&#39;O&#39;, &#39;L&#39;), (&#39;O&#39;, &#39;C&#39;), (&#39;L&#39;, &#39;C&#39;)]
listb.index(i) : [(&#39;O&#39;, &#39;L&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;L&#39;, &#39;E&#39;)]
listb.index(i) : [(&#39;O&#39;, &#39;I&#39;), (&#39;O&#39;, &#39;C&#39;), (&#39;I&#39;, &#39;C&#39;)]
listb.index(i)=n : [(&#39;O&#39;, &#39;I&#39;), (&#39;O&#39;, &#39;E&#39;), (&#39;I&#39;, &#39;E&#39;)]
登入後複製

二维列表 listb ,其中的行(发音:hang,二声。横着的那排)从上到下就是第一层for循环 ;每一行中的i[0],i[1],i[2]就是第二层for循环从左至右;第三次for循环元素i[x]从上之下与有效组 templistb通位置元素的对比。

1、第n行的i[0]要和有效templistb的其他行的i[0]元素对比(第三for),如果有相等的,记录一个标识 如 flag1=True,如果没有相等的记录falg1=False;

2、直到第二for中的i[0],i[1],i[2]都进行对比后,会得到 [flag1,flag2,flag3 ],所有flag=True则该行为无效用例

3、第一for遍历全部组合,最终得到保留下来的有效templistb

见图:

完结篇

以上是自己编写的pairwise的全部内容,此算法共耗时3天:

第一天在确定这究竟是什么算法,看了很多学术文献,看不懂;

第二天开始写程序,for的嵌套循环设计耽误很久;

第三天程序成型,有执行结果,发现与参考文章结论不同,随后再仔细研读参考文章,发现掉坑里了。重新推翻代码按照正确思路,用1个小时完成最终结果。

本人做测试的,还不是专业的测试开发,写代码比较费劲,真正应了设计占70%,编码占30%的理。如果像基础在差点,逻辑在乱点,就只能用时间堆了。

以上是Python如何實作組織演算法pairwise(高效測試用例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板