朱曉程 薛 靜 楊 彬 閆雪麗
北京航天自動(dòng)控制研究所,北京100854
并發(fā)軟件設(shè)計(jì)的運(yùn)用已越來越普遍,它能夠提高程序執(zhí)行效率與系統(tǒng)資源的利用率,但與此同時(shí),由于并發(fā)軟件執(zhí)行時(shí)行為的不確定性,造成軟件問題更加復(fù)雜且難以解決。并發(fā)軟件的發(fā)展對軟件測試技術(shù)提出了更高的要求,目前,并發(fā)軟件測試主要存在以下問題:
1)程序執(zhí)行的不確定性,與順序執(zhí)行的程序相比,可測試性低,并發(fā)問題難以定位與測試;
2)隨機(jī)輸入程序執(zhí)行過程的并發(fā)事件序列的不確定性測試[1](Non-deterministic Testing),難以保證測試的充分性,測試效果不理想;
3)控制程序執(zhí)行過程并發(fā)事件序列的確定性測試[1](Deterministic Testing),不同的同步序列生成方法選擇,可能會(huì)使得并發(fā)測試用例數(shù)量爆炸,影響測試效率。
模型驅(qū)動(dòng)測試方法可實(shí)現(xiàn)測試前移,滿足軟件測試驗(yàn)證與軟件設(shè)計(jì)開發(fā)的并行研制需求,改變軟件測試滯后于軟件開發(fā)的基本狀況。因此,基于模型的測試用例生成方法也越來越迎合該行業(yè)技術(shù)發(fā)展的要求。活動(dòng)圖是UML[2](統(tǒng)一建模語言)中一種重要的、用于描述系統(tǒng)工作流程的模型圖,它描述系統(tǒng)活動(dòng)的順序及控制流,并且能夠表述同時(shí)發(fā)生的活動(dòng)。這使得活動(dòng)圖適用于建立工作流模型、分析用例以及分析多線程應(yīng)用程序。
數(shù)據(jù)競爭是并發(fā)軟件最常見的故障,且多數(shù)并發(fā)故障的本質(zhì)是由于共享資源的不合理保護(hù),產(chǎn)生數(shù)據(jù)競爭問題而造成的,因此,針對并發(fā)軟件特性提出對活動(dòng)圖進(jìn)行資源屬性的擴(kuò)展,提出了基于資源擴(kuò)展活動(dòng)圖的并發(fā)測試用例生成方法,通過該方法提高并發(fā)測試用例的生成質(zhì)量與效率。
UML定義活動(dòng)圖是一種UML行為圖,它用于描述控制或?qū)ο罅鞯牧?,重點(diǎn)描述流的順序和條件。
活動(dòng)圖的基本組成元素包括:初始節(jié)點(diǎn)、活動(dòng)節(jié)點(diǎn)、活動(dòng)終點(diǎn)、轉(zhuǎn)換、判定、分叉與合并。
1)初始節(jié)點(diǎn),用實(shí)心圓表示活動(dòng)圖的開始,只有1個(gè);
2)活動(dòng)終點(diǎn),1個(gè)實(shí)心圓外加1個(gè)圓圈,可以有多個(gè);
3)活動(dòng)節(jié)點(diǎn),表示工作流程中執(zhí)行的步驟,彼此間通過轉(zhuǎn)換連接;
4)轉(zhuǎn)換,是有向連接線,用于描述活動(dòng)節(jié)點(diǎn)間的轉(zhuǎn)換關(guān)系,前一個(gè)活動(dòng)節(jié)點(diǎn)結(jié)束,沿著轉(zhuǎn)換連接進(jìn)入下一個(gè)活動(dòng)節(jié)點(diǎn)執(zhí)行;
5)判定,用菱形表示,輸入為一個(gè)轉(zhuǎn)換,輸出為一個(gè)轉(zhuǎn)換,判定條件用于指導(dǎo)下一步執(zhí)行的轉(zhuǎn)換;
6)分叉與合并,都是用加粗的水平線段表示,其中分叉用于描述2個(gè)或2個(gè)以上并發(fā)運(yùn)行的分支,可以用于描述程序的并發(fā)處理,分叉包括一個(gè)輸入轉(zhuǎn)換和不少于2個(gè)的輸出轉(zhuǎn)換;合并,與分叉相對出現(xiàn),用于描述并發(fā)運(yùn)行的分支都達(dá)到合并點(diǎn)后,控制才往下繼續(xù)執(zhí)行,合并包括不少于2個(gè)的輸入轉(zhuǎn)換和一個(gè)輸出轉(zhuǎn)換。
活動(dòng)圖基本元素表示如圖1所示:
圖1 活動(dòng)圖基本組成元素
活動(dòng)、轉(zhuǎn)換是活動(dòng)圖中的核心,軟件測試應(yīng)至少保證每個(gè)活動(dòng)及表達(dá)活動(dòng)驅(qū)動(dòng)關(guān)系的轉(zhuǎn)換被執(zhí)行一次,即基本路徑覆蓋原則[3]。除此之外,針對并發(fā)系統(tǒng),應(yīng)關(guān)注共享資源使用、任務(wù)同步關(guān)系處理的考核,鑒于此,提出并發(fā)處理的測試覆蓋策略:
1)資源等待覆蓋:每一個(gè)共享資源,對于使用它的每一個(gè)并發(fā)任務(wù)至少要等待一次資源獲?。?/p>
2)資源釋放覆蓋:每一個(gè)共享資源,對于使用它的每一個(gè)并發(fā)任務(wù)至少要獲取它一次,驗(yàn)證資源釋放;
3)任務(wù)同步覆蓋:具有邏輯依賴關(guān)系的任務(wù),不同任務(wù)間的同步關(guān)系至少被覆蓋一次。
事實(shí)上,任務(wù)優(yōu)先級的設(shè)置也是并發(fā)軟件設(shè)計(jì)的重要方面,隨著硬件技術(shù)的發(fā)展,多核處理器的運(yùn)用對并發(fā)軟件設(shè)計(jì)產(chǎn)生了影響,考慮并發(fā)測試本身的難度,降低測試分析的復(fù)雜性,對于任務(wù)優(yōu)先級設(shè)置及多核處理的影響的考核,可以進(jìn)行單獨(dú)的測試分析與設(shè)計(jì),在此不進(jìn)行過多關(guān)注,同時(shí)為了便于活動(dòng)圖對并發(fā)系統(tǒng)的描述,做以下抽象:
1)對共享資源的保護(hù)采用統(tǒng)一的方式;
2)任務(wù)間的同步操作采用統(tǒng)一的方式;
3)軟件執(zhí)行的硬件為單核處理器;
4)任務(wù)數(shù)為可表達(dá)測試覆蓋原則及用例生成方法的最小集合。
活動(dòng)圖中路徑及任務(wù)同步序列的全覆蓋,會(huì)隨著任務(wù)對象及活動(dòng)的增長呈現(xiàn)爆發(fā)式增長,測試用例數(shù)量會(huì)相當(dāng)龐大。因此需要研究一種方法,它能夠在選取較少測試用例集的情況下,具有較充分的測試驗(yàn)證能力。
利用活動(dòng)圖進(jìn)行建模,首先應(yīng)對活動(dòng)圖進(jìn)行形式化的符號(hào)描述,以便于算法的描述。
定義1[4]活動(dòng)圖D是一個(gè)六元組,D=(A,T,W,G,F,J),其中,
A={a0 ,a1 , …,am}是一個(gè)有限活動(dòng)集;
T={t0 ,t1, …,tn}是一個(gè)有限轉(zhuǎn)換集;
W包含于(A×T)∪(T×A)是活動(dòng)圖的轉(zhuǎn)換關(guān)系 ;
G(t)是轉(zhuǎn)換的條件表達(dá)式;
F={f0,f1,…,fm}是一個(gè)有限分叉集,其中元素為活動(dòng)圖中并發(fā)路徑的起始點(diǎn);
J={j0,j1,…,jn}是一個(gè)有限合并集,其中元素為活動(dòng)圖中并發(fā)路徑的終止點(diǎn);
集合A中有且只有一個(gè)元素a0∈A是初始節(jié)點(diǎn);
集合A中至少有一個(gè)元素af∈A是活動(dòng)終點(diǎn);對于任何t′∈T,(t′,a0)不屬于W, 且(af,t′)不屬于W。
定義2活動(dòng)圖中的路徑集合L是活動(dòng)圖D中活動(dòng)與轉(zhuǎn)換的有向序列集合:
L={l0,l1,…,ln};
li=a0-t1->a2-t2->fi…-tx->ji-tq->ap-tp->af;
其中,ai∈A,是活動(dòng)集中的元素;tj∈T,是轉(zhuǎn)換集中的元素;fi∈F,是分叉集中的元素;ji∈J,是合并集中的元素。
定義num(x)為集合X中元素個(gè)數(shù),則對于任意路徑L,滿足num(ai)>=1;
若路徑元素li、lj中同時(shí)包含任意元素fi,則定義li與lj為并發(fā)路徑。
定義3活動(dòng)圖中活動(dòng)執(zhí)行的優(yōu)先級關(guān)系:
ai ai>aj,表示活動(dòng)ai晚于aj執(zhí)行; ai||aj,表示活動(dòng)aj與aj無執(zhí)行順序的制約關(guān)系,并發(fā)執(zhí)行。 其中,ai、aj∈A,是活動(dòng)集中的元素。 3.2.1 基本路徑測試用例生成 為了描述基本路徑用例生成方法,舉例活動(dòng)圖如下,其中,為了簡化路徑表達(dá),將活動(dòng)圖中節(jié)點(diǎn)進(jìn)行抽象,轉(zhuǎn)化為活動(dòng)圖的簡化流圖?;顒?dòng)圖及簡化流圖如圖2所示。 圖2 活動(dòng)圖及簡化流圖示例 基本路徑覆蓋原則:活動(dòng)圖中從初始狀態(tài)到終止?fàn)顟B(tài)間每條路徑被覆蓋一次,對于循環(huán)路徑,只覆蓋一次。 定義活動(dòng)圖簡化流圖的基本路徑集合為LS={lsi|i=0,1,…,n}; 圖2基本路徑集合LS中元素有2條,如下: ls1=0→1→2→4 ls2=0→1→3→4。 定義測試用例集為TC={tci|,對于任意ri至少存在一個(gè)tci,ri運(yùn)行時(shí)tci被執(zhí)行}。 3.2.2 基本并發(fā)路徑測試用例生成 對于一個(gè)描述并發(fā)任務(wù)的活動(dòng)圖,路徑測試覆蓋策略應(yīng)考慮分叉以后任務(wù)間活動(dòng)的關(guān)系,分叉的后繼節(jié)點(diǎn)(與分叉有直接連接關(guān)系的節(jié)點(diǎn),順序上在分叉之后)在執(zhí)行的順序關(guān)系上應(yīng)進(jìn)行排列組合,才能保證用例的充分性。圖3為一個(gè)描述并發(fā)系統(tǒng)的活動(dòng)圖及簡化流圖。 圖3 并發(fā)活動(dòng)圖及簡化流圖示例 基本并發(fā)路徑覆蓋原則:在基本路徑覆蓋原則的基礎(chǔ)之上,對分叉節(jié)點(diǎn)的后繼節(jié)點(diǎn)的排列組合進(jìn)行覆蓋,如分叉后繼節(jié)點(diǎn)a1、a2,并發(fā)路徑的覆蓋為a1→a2,a2→a1,對分叉后非直接連接的節(jié)點(diǎn)a3,滿足a1 通過上述原則生成圖的12條基本并發(fā)路徑集合LS: ls1=0→1→2→3→4→5→6→7→8 ls2=0→1→2→3→4→6→5→7→8 ls3=0→1→2→3→5→4→6→7→8 ls4=0→1→2→3→5→6→4→7→8 ls5=0→1→2→3→6→4→5→7→8 ls6=0→1→2→3→6→5→4→7→8 ls7=0→1→2→4→3→6→5→7→8 ls8=0→1→2→4→3→5→6→7→8 ls9=0→1→2→4→5→3→6→7→8 ls10=0→1→2→5→3→6→4→7→8 ls11=0→1→2→5→3→4→6→7→8 ls12=0→1→2→5→4→3→6→7→8 3.2.3 并發(fā)測試用例規(guī)模計(jì)算 通過基本并發(fā)路徑覆蓋原則生成并發(fā)測試用例,當(dāng)系統(tǒng)中并發(fā)活動(dòng)數(shù)量、并發(fā)線程數(shù)量增多,按照任意順序?qū)顒?dòng)進(jìn)行排列組合,會(huì)導(dǎo)致用例數(shù)量急劇增長。 定義4軟件系統(tǒng)中并發(fā)任務(wù)數(shù)量為m,分叉節(jié)點(diǎn)到合并節(jié)點(diǎn)間活動(dòng)數(shù)量為n,每個(gè)并發(fā)任務(wù)的活動(dòng)數(shù)量的集合為Q={qi|qi為每個(gè)并發(fā)任務(wù)中活動(dòng)的數(shù)量,1≤i≤m}。 通過基本并發(fā)路徑覆蓋原則生成的測試路徑數(shù)量為 利用圖3對上述計(jì)算公式進(jìn)行驗(yàn)證。 從分叉到合并節(jié)點(diǎn)間(即簡化流圖中)的任務(wù)數(shù)m=3; 從分叉到合并節(jié)點(diǎn)間的活動(dòng)數(shù)n=4; 每個(gè)并發(fā)任務(wù)的活動(dòng)數(shù)量為集合Q={q1=2,q2=1,q3=1}; 從上述推導(dǎo)中可以得出,滿足基本并發(fā)路徑覆蓋原則生成的測試用例數(shù)量隨著并發(fā)活動(dòng)的總數(shù)成階乘級別增長,有限數(shù)量的并發(fā)活動(dòng)即可造成測試用例數(shù)量爆炸。 3.3.1 資源擴(kuò)展活動(dòng)圖 通過之前的實(shí)驗(yàn)分析,揭露了普通活動(dòng)圖描述并發(fā)系統(tǒng)存在缺點(diǎn): 1)活動(dòng)圖的抽象層次較高,能夠表述活動(dòng)的并發(fā)關(guān)系,但對共享資源使用缺少描述,進(jìn)而難以利用普通活動(dòng)圖生成充分的并發(fā)測試用例; 2)基本路徑覆蓋的測試策略對并發(fā)任務(wù)間的同步關(guān)系及共享資源的訪問沖突的考核缺少針對性; 3)基本并發(fā)路徑覆蓋的測試策略產(chǎn)生的測試用例隨并發(fā)活動(dòng)數(shù)成階乘級別增長。 鑒于以上分析,思考將活動(dòng)圖進(jìn)行擴(kuò)展以達(dá)到在滿足測試充分性的條件下盡量減少用例數(shù)量的目的。對于并發(fā)任務(wù)而言,并發(fā)任務(wù)間的活動(dòng)若無資源訪問、同步通信的耦合關(guān)系,二者的全排列組合不會(huì)影響軟件的操作結(jié)果及輸出,也就是說這些活動(dòng)全排列組合產(chǎn)生的測試用例,從測試效果上存在用例重復(fù)設(shè)計(jì)。若將共享資源的使用引入活動(dòng)圖中,定義擴(kuò)展活動(dòng)圖,不僅能夠更準(zhǔn)確地描述并發(fā)系統(tǒng)工作流程,更重要的是能夠排除無耦合關(guān)系活動(dòng)間的全排列組合產(chǎn)生的路徑,很大程度上減少測試用例數(shù)量,提高測試的效率及準(zhǔn)確性。 在活動(dòng)圖中引入資源狀態(tài),資源狀態(tài)為用于描述被多個(gè)活動(dòng)訪問的共享資源,通過引入資源狀態(tài)描述并發(fā)任務(wù)間與資源相關(guān)的耦合關(guān)系,以排除無耦合關(guān)系的并發(fā)測試路徑。 定義5資源擴(kuò)展活動(dòng)圖Dr是一個(gè)七元組,Dr=(A,T,W,G,F,J,R),其中,R為活動(dòng)圖中共享資源狀態(tài)集合,R={ri|ri在活動(dòng)圖中至少被2個(gè)并發(fā)活動(dòng)所訪問,i=1,2…,n}。其余元素定義同定義1。 將圖3進(jìn)行資源擴(kuò)展,假使圖中動(dòng)作狀態(tài)a2、a3間的共享資源為r1,a4、a5間的共享資源為r2,資源擴(kuò)展活動(dòng)圖見圖4左側(cè)。基于前文所示的并發(fā)測試覆蓋策略,使每個(gè)任務(wù)對資源的訪問至少考核一次資源等待、一次資源釋放操作。資源擴(kuò)展活動(dòng)圖的簡化流圖應(yīng)凸顯共享資源的并發(fā)訪問,簡化無資源關(guān)聯(lián)的任務(wù)關(guān)系。因此,簡化流圖的繪制相對于普通活動(dòng)圖做以下改變: 1)以資源作為中心,簡化流圖的數(shù)量與資源的數(shù)量一一對應(yīng); 2)并發(fā)關(guān)系不再以“分叉”為起點(diǎn),改以共享資源為起點(diǎn); 3)無資源關(guān)聯(lián)的并發(fā)活動(dòng)由并發(fā)結(jié)構(gòu)變換為順序結(jié)構(gòu); 4)活動(dòng)在不同簡化流圖中按照一致順序排列; 5)圖中并發(fā)活動(dòng)按照BFS(廣度優(yōu)先搜索)遍歷順序編號(hào)。 圖4左側(cè)資源擴(kuò)展活動(dòng)圖通過以上規(guī)則繪制簡化流圖如圖4右側(cè)。 圖4 資源擴(kuò)展活動(dòng)圖及簡化流圖示例 3.3.2 資源擴(kuò)展活動(dòng)圖用例生成 資源擴(kuò)展活動(dòng)圖的每一個(gè)簡化流圖與一個(gè)共享資源一一對應(yīng),對每一個(gè)子流圖只需關(guān)注該圖中資源的并發(fā)使用關(guān)系,對于并發(fā)訪問的活動(dòng),無需進(jìn)行活動(dòng)的全排列組合,只通過循環(huán)排列即可滿足一次資源等待、一次資源釋放的測試覆蓋策略。所謂循環(huán)排列,即將訪問同一資源的活動(dòng)用一個(gè)循環(huán)隊(duì)列來存儲(chǔ),記錄循環(huán)隊(duì)列原始頭,順序從隊(duì)列頭訪問置隊(duì)列尾,形成一次排列,結(jié)束后,將頭元素出隊(duì)循環(huán)插入隊(duì)尾,按此規(guī)律生成全部排列直至再次訪問到原始頭結(jié)束。此過程示意圖如圖5。 圖5 測試路徑生成示意圖 通過上述用例生成方法,生成圖4的各子流圖中并發(fā)測試路徑集合。 子流圖1: ls11=0→1→2→3→4→5→6→7 (首路徑) ls12=0→1→3→2→4→5→6→7 子流圖2: ls21=0→1→2→3→4→5→6→7 (首路徑) ls22=0→1→2→3→5→4→6→7 按照3.3.1中資源擴(kuò)展活動(dòng)圖的繪制原則產(chǎn)生各簡化流圖中的首路徑是彼此重復(fù)的,生成的測試路徑數(shù)量總和應(yīng)為各子流圖路徑數(shù)量減去重復(fù)路徑數(shù)。將子流圖1和2的測試路徑取并集,獲得圖4測試路徑集合: ls1=0→1→2→3→4→5→6→7 ls2=0→1→3→2→4→5→6→7 ls3=0→1→2→3→5→4→6→7 實(shí)際上,ls2與ls3可以通過ls4= 0→1→3→2→5→4→6→7進(jìn)行替代,進(jìn)一步減少用例數(shù)量。但活動(dòng)與資源的關(guān)系可以是無序網(wǎng)型拓?fù)浣Y(jié)構(gòu),合并方式靈活,但會(huì)增加用例設(shè)計(jì)的復(fù)雜性,考慮用例生成效率,不再對路徑做進(jìn)一步復(fù)雜合并,本方法已較大程度地篩檢了重復(fù)用例數(shù),提高了用例設(shè)計(jì)的效率。如此例相較于未經(jīng)資源擴(kuò)展的活動(dòng)圖3(測試路徑數(shù)12個(gè)),生成的測試路徑數(shù)明顯減少。 在測試用例數(shù)與測試路徑數(shù)一一對應(yīng)的關(guān)系下,通過上述方法生成的測試用例數(shù)量: 其中,R為共享資源集合;num(R)為集合元素總數(shù);pi∈P,P={pi|pi為訪問共享資源ri的活動(dòng)數(shù)}。 從上述推導(dǎo)中可以得出,基于資源擴(kuò)展活動(dòng)圖的并發(fā)測試用例生成方法生成的用例數(shù)量與訪問共享資源的活動(dòng)總數(shù)為線性關(guān)系,相較于未擴(kuò)展的活動(dòng)圖的基本路徑覆蓋方法,用例數(shù)量明顯減少,有效地防止了測試用例數(shù)量爆炸的問題。 選取航天某型號(hào)主控軟件的部分功能作為實(shí)例驗(yàn)證該方法的有效性。主控軟件的時(shí)間同步功能為:接收上級指控系統(tǒng)的時(shí)間信息,更新本機(jī)時(shí)間,將更新后時(shí)間發(fā)送至本系統(tǒng)內(nèi)其他設(shè)備,同時(shí)軟件界面更新時(shí)間顯示。與該功能相關(guān)的并發(fā)任務(wù)有4個(gè),分別是接收信息任務(wù)RecvTask、發(fā)送任務(wù)SendTask、軟件功能主任務(wù)MainTask及界面更新任務(wù)UpdateTask,各任務(wù)功能均為循環(huán)執(zhí)行,在程序退出前不結(jié)束執(zhí)行。 該功能相應(yīng)的活動(dòng)圖見圖6。 圖6 主控軟件時(shí)間同步功能活動(dòng)圖 按照本文定義4,生成測試路徑的相關(guān)參數(shù)值分別為: 并發(fā)任務(wù)數(shù)量m=4; 分叉節(jié)點(diǎn)到合并節(jié)點(diǎn)間活動(dòng)數(shù)量n=6; 每個(gè)并發(fā)任務(wù)的活動(dòng)數(shù)量的集合Q={1,3,1,1}。 按照改進(jìn)前的用例生成方法計(jì)算測試用例數(shù)量N=120。 按照本文的方法生成測試用例,分析程序共享資源的使用情況,見表1。 表1 資源使用情況 繪制資源擴(kuò)展活動(dòng)圖,見圖7。 圖7 主控軟件時(shí)間同步功能資源擴(kuò)展活動(dòng)圖 通過繪制資源擴(kuò)展活動(dòng)圖的簡化流圖,獲得測試路徑包括4條,如下: ls1=0→1→2→3→4→5→6→7→8 ls2=0→1→7→3→4→5→6→2→8 ls3=0→1→2→4→3→5→6→7→8 ls4=0→1→2→3→4→6→5→7→8 使用上述測試路徑對被測軟件該部分處理進(jìn)行考核,發(fā)現(xiàn)界面更新的時(shí)間值顯示異常,存在時(shí)間值為0的閃現(xiàn)情況。問題發(fā)生的原因?yàn)镸ainTask在更新時(shí)間值時(shí)首先將存儲(chǔ)時(shí)間的變量復(fù)位為0,但未進(jìn)行共享資源保護(hù)處理。經(jīng)需求分析,此變量復(fù)位為0的處理為多余處理,刪除程序中的相關(guān)語句,該軟件問題得到解決。 通過上述實(shí)例證明,本文方法能夠在減少測試用例數(shù)量的同時(shí)生成充分、有效的測試用例。 從生成并發(fā)測試用例的目的出發(fā),提出了擴(kuò)展活動(dòng)圖的描述方法,分析基于活動(dòng)圖的并發(fā)測試覆蓋策略,從而提出基于擴(kuò)展活動(dòng)圖的并發(fā)軟件測試用例生成方法。利用該方法生成的測試用例能夠檢測多線程軟件共享資源保護(hù)異常、任務(wù)同步缺陷等并發(fā)軟件問題,減少測試用例數(shù)量,防止用例數(shù)量爆炸,提高軟件測試質(zhì)量與效率。未來,利用該方法結(jié)合擴(kuò)展活動(dòng)圖的形式化描述及模型工具,可以進(jìn)一步研究測試用例生成的自動(dòng)化工具,使本方法的應(yīng)用更準(zhǔn)確、更效率。3.2 測試用例生成方法
3.3 基于資源擴(kuò)展活動(dòng)圖的并發(fā)測試用例生成方法
4 實(shí)例驗(yàn)證
5 結(jié)論