摘 要: 軟件體系結(jié)構(gòu)用來描述系統(tǒng)的高層結(jié)構(gòu)和行為特征,軟件體系結(jié)構(gòu)描述語言ADLs是對軟件體系結(jié)構(gòu)的形式化描述。在軟件體系結(jié)構(gòu)描述語言Wright的基礎(chǔ)上,引入了一種圖形的表示方法,即以動態(tài)行為圖(BG圖)來表示相關(guān)的構(gòu)件間的動態(tài)行為及它們之間的關(guān)系,并提出了軟件體系結(jié)構(gòu)測試覆蓋準(zhǔn)則。根據(jù)BG圖中路徑的定義,給出了BG圖中測試路徑生成算法的基本思想。以C/S體系結(jié)構(gòu)為例,驗證了該方法在生成SA級的測試路徑上是可行的。
關(guān)鍵詞: 軟件體系結(jié)構(gòu); 軟件測試; 測試路徑; 動態(tài)行為圖; 測試覆蓋準(zhǔn)則
利用軟件體系結(jié)構(gòu)模型來指導(dǎo)測試是目前軟件測試的一個重要研究領(lǐng)域。依據(jù)參考文獻(xiàn)[1]的定義,SA基本組成元素包括構(gòu)件、連接件、配置和約束。構(gòu)件是一個計算單元或一個數(shù)據(jù)存儲單元;連接件是體系結(jié)構(gòu)中的“粘合劑”,用于建模構(gòu)件間交互并定義交互規(guī)則;配置是一種拓?fù)浣Y(jié)構(gòu),用來描述系統(tǒng)中的構(gòu)件與連接件之間的關(guān)系;約束是關(guān)于系統(tǒng)或其一部分性質(zhì)或斷言。
軟件體系結(jié)構(gòu)描述語言ADLs從不同方面對軟件體系結(jié)構(gòu)進(jìn)行規(guī)約和建模分析,是對軟件體系結(jié)構(gòu)的形式化描述。典型的ADL包括UniCon、Rapide、Darwin、Wright、C2 SADL、Acme、xADL、XYZ/ADL和ABC/ADL等[2]。
目前軟件體系結(jié)構(gòu)測試主要集中在建立測試抽象模型及體系結(jié)構(gòu)動態(tài)特征的提取。Jin Zhenyi和OFFUTT J用Wright語言描述軟件體系結(jié)構(gòu),生成基于ICG圖和BG圖的測試用例[3]。ROBERT A[4]引入體系結(jié)構(gòu)描述語言Wright,為描述和分析軟件體系結(jié)構(gòu)和結(jié)構(gòu)類型提供一種有效方式。BERTOLINO A[5]等人提出利用化學(xué)抽象機(jī)形式化描述SA,定義了基于化學(xué)抽象機(jī)的模型和測試覆蓋準(zhǔn)則,由此導(dǎo)出基于結(jié)構(gòu)描述的測試計劃。ABDURAZIK A等人針對軟件體系結(jié)構(gòu)描述,提出了通用的體系結(jié)構(gòu)測試覆蓋準(zhǔn)則[6]。ROSENBLUM[7]提出基于構(gòu)件的軟件測試?yán)碚?,指出這種技術(shù)在綜合層要優(yōu)于結(jié)構(gòu)層,同時也依賴于執(zhí)行的完整性。
本文提出一種基于Wright的新技術(shù)。以Client/ Server體系結(jié)構(gòu)的Wright描述為模型,提出了相應(yīng)的測試覆蓋準(zhǔn)則,生成此結(jié)構(gòu)的動態(tài)行為圖以及相應(yīng)的測試路徑,文中還給出了基于此結(jié)構(gòu)的測試路徑生成算法的基本思想。
1 Wright和BG圖
1.1 Wright
Wright是一種通用的軟件體系結(jié)構(gòu)描述語言,它對體系結(jié)構(gòu)中構(gòu)件、連接件以及它們之間的一組約束進(jìn)行形式化描述,為體系結(jié)構(gòu)配置和體系結(jié)構(gòu)風(fēng)格的描述提供實用的形式化基礎(chǔ)。Wright中構(gòu)件間的行為及合作是利用CSP中的符號來指定的。CSP中,確定構(gòu)件間行為以及交互模式的符號主要包括:事件e、進(jìn)程P、e?x表示進(jìn)程接收數(shù)據(jù)x、e!x表示進(jìn)程輸出數(shù)據(jù)x、§表示系統(tǒng)成功終止、e→P表示進(jìn)程首先執(zhí)行事件e然后啟動進(jìn)程P、□表示外部選擇(選擇由外部環(huán)境決定)、∏表示內(nèi)部選擇(選擇由進(jìn)程自身決定);表示按順序連接兩個進(jìn)程。下面以Client/Server體系結(jié)構(gòu)為例,給出該結(jié)構(gòu)的Wright描述:
Component Client
Port Service=ClientPullT
Computation=Service.open;UseOrExit
where UseOrExit=UserService∏ExitUseService=Service.
request→Service.result?y→UseOrExit
Exit=Service.close→§
Component Server
Port Provide=ServerPushT
Computation=WaitForClient□Exit§
where WaitForClient=Provide.open→Provide.request→
Provide.result?x→WaitForClient
Exit=Provide.close→§
Connector C-S Connector
Role Client=ClientPullT
Role Server=ServerPushT
Glue=Client.open→Server.open→Glue□Client.close→
Server.close→Glue□Client.request→Server.request→
Glue□Server.result?x→Client.result!x→Glue□§
Type ClientPullT=open→Operate∏§
where Operate=request→result?x→Operate∏Close
Close=close→§
Type ServerPushT= open→Operate□§
where Operate=request→result!x→Operate□Close
Close=close→§
Instances
c: Client
s: Server
cs: C-S Connector
Attachments:
c provides as cs.c
s provides as cs.S
end
1.2 動態(tài)行為圖(BG圖)
Wright給出了構(gòu)件、連接件及其接口的行為描述,以及它們之間是如何工作的,為在測試中反映這些信息,本文引入一種新型的圖形表示方法,即BG圖(Behavior Graph),表示構(gòu)件間和它們之間連接的接口行為信息。BG圖主要基于Petri網(wǎng)理論[8],同時在Petri網(wǎng)理論中增加了外部選擇和內(nèi)部選擇信息。
定義1 構(gòu)件間動態(tài)行為圖BG=(COMPi(Pn1,Tn1, In1,On1),COMPj(Pn2,Tn2,In2,On2),Pc,Tc,Ic,Oc),其中 COMPi、COMPj分別是對構(gòu)件Ni、Nj的描述;Pn是構(gòu)件N的庫所集,Tn是變遷集,In是輸入弧集,On是輸出弧集;Pc是兩個構(gòu)件間的庫所集;Tc是兩個構(gòu)件間的變遷集且Pn1∩Pn2∩Pc=Φ,Tn1∩Tn2∩Tc=Ic是兩個構(gòu)件間庫所到變遷弧的集合,Ic:({Pni,Pnj,Pc}×{Tni,Tnj,Tc})→{0,1},該值為1表明構(gòu)件i的庫所到構(gòu)件j的變遷有弧存在;否則構(gòu)件i的庫所到構(gòu)件j的變遷沒有弧存在;Oc是兩個構(gòu)件間變遷到庫所弧的集合,Oc:({Tni,Tnj,Tc}×{Pni,Pnj,Pc})→{0,1},該值為1表明構(gòu)件i的變遷到構(gòu)件j的庫所有弧存在;否則構(gòu)件i的變遷到構(gòu)件j的庫所沒有弧存在。
從C/S結(jié)構(gòu)的Wright描述轉(zhuǎn)換到該結(jié)構(gòu)的BG圖可以根據(jù)已有的理論[9],圖1給出了與Wright描述相對應(yīng)的C/S結(jié)構(gòu)的BG圖。C/S結(jié)構(gòu)遵循如下規(guī)則:

Client端或初始化進(jìn)程與Server端建立連接client.open,或什么也不做結(jié)束進(jìn)程client.§1,一旦連接建立,Client端向Server端發(fā)送請求client.request,Server端打開與Client端建立的連接。當(dāng)Server端接收來自Client端的請求server.request時,Server端向Client端返回請求結(jié)果server.result!x;然后Server端等待Client端發(fā)送更多請求;當(dāng)Client端接收到自Server端的請求結(jié)果client.result?x,Client端可以向Server端發(fā)送更多的請求,也可關(guān)閉連接client.close。如果Client端關(guān)閉連接,迫使Server端也關(guān)閉連接、結(jié)束進(jìn)程。
設(shè)COMP1為Client component,COMP2為Server component,根據(jù)定義1有:
BG=(COMP1(Pn1,Tn1,In1,On1), COMP2(Pn2,Tn2,In2,On2),Pc,Tc,Ic,Oc)
Client:
Pn1={(client.p0,client.p1,client.p2,client.p3,client.p4,client.p5)}
Tn1={(client.open,client.request,client.result,client.close,client.
§1,cleint.§2)}
In1={(client.p0,client.open),(client.p1,client.request),(client.p2,
client.result),(client.p1,client.close),(client.p0,client.§1),
(client.p4,client.§2)}
On1={(client.open,client.p1),(client.§1,client.p3),(client.
request,client.p2),(client.result,client.p1),(client.§2,client.
p5),(client.close,client.p4)}
Server:
Pn2={(server.p0,server.p1,server.p2,server.p3,server.p4,server.
p5)}
Tn2={(server.open,server.request,server.result,server.close,server.
§1,server.§2)}
In2={(server.p0,server.open),(server.p1,server.request),(server.
p2,server.result),(server.p1,server.close),(server.p4,server.
§2),(server.p0,server.§1)}
On2={(server.open,server.p1),(server.request,server.p2),(server.
result,server.p1),(server.§1,server.p3),(server.close,server.
p4),(server.§2, server.p5)}
Pc={p101,p102,p103,p104}
Tc={}
Ic={(p101,server.open),(p102,server.request),(p103,server.close),
(p104,client.result)}
Oc={(client.open,p101),(client.request,p102),(server.result,p104),
(Client.close,p103)}
2 軟件體系結(jié)構(gòu)測試覆蓋準(zhǔn)則
為了有效地產(chǎn)生測試用例,需要定義一組體系結(jié)構(gòu)層的測試覆蓋準(zhǔn)則。具體可定義以下六種測試覆蓋準(zhǔn)則:
(1)構(gòu)件(連接件)內(nèi)部傳遞關(guān)系覆蓋準(zhǔn)則:軟件體系結(jié)構(gòu)中所有構(gòu)件(連接件)接口間內(nèi)部數(shù)據(jù)流或控制流關(guān)系至少分析一次。
(2)構(gòu)件(連接件)內(nèi)部順序關(guān)系覆蓋準(zhǔn)則:軟件體系結(jié)構(gòu)中所有構(gòu)件(連接件)接口間行為應(yīng)遵循某些必要的執(zhí)行規(guī)則至少分析一次。
(3)構(gòu)件-連接件關(guān)系(連接件-構(gòu)件關(guān)系)覆蓋準(zhǔn)則:軟件體系結(jié)構(gòu)中所有構(gòu)件(連接件)接口與對應(yīng)的連接件(構(gòu)件)接口間存在的關(guān)聯(lián)關(guān)系至少分析一次。
(4)直接構(gòu)件關(guān)系覆蓋準(zhǔn)則:軟件體系結(jié)構(gòu)中構(gòu)件-連接件關(guān)系、連接件-構(gòu)件關(guān)系和連接件內(nèi)部關(guān)系至少分析一次。
(5)間接構(gòu)件關(guān)系覆蓋準(zhǔn)則:若構(gòu)件Ni和構(gòu)件Nj(i≠j)間存在非直接關(guān)聯(lián)路徑,則該路徑至少分析一次。
(6)全連接構(gòu)件覆蓋準(zhǔn)則:若存在全連接構(gòu)件路徑N1-C1-…-Ct-Ns,則該路徑N1-C1-…-Ct-Ns至少分析一次。
3 基于BG圖的測試路徑生成方法
3.1 B-路徑生成算法
根據(jù)BG圖可以給出以下關(guān)于測試路徑的定義:
定義2 BG圖中的路徑:一條BG圖中的路徑是由k個庫所(遷移)的節(jié)點和k-1條弧構(gòu)成,對于整數(shù)k,第i條弧或者連接第i個節(jié)點到第i+1個節(jié)點或者連接第i+1個節(jié)點到第i個節(jié)點。
定義3 構(gòu)件內(nèi)部行為路徑(B-路徑):在一個構(gòu)件接口的子網(wǎng)內(nèi),它起始于開始庫所,終止于結(jié)束庫所,當(dāng)在子網(wǎng)內(nèi)存在環(huán)時,在每條B-路徑中,有且只有一個環(huán)存在。每個庫所(變遷)在每條B-路徑中最多被訪問兩次。
定義4 構(gòu)件連接路徑(C-路徑):C-路徑通過兩個構(gòu)件子網(wǎng)A和B,它起始于構(gòu)件子網(wǎng)A的一個庫所,終止于構(gòu)件子網(wǎng)B的一個庫所,在軟件體系結(jié)構(gòu)的上下文中,兩個構(gòu)件之間的連接通常都是從一個構(gòu)件的遷移到另一個構(gòu)件的遷移。
下面以B-路徑為例,給出BG圖中B-路徑的生成算法,在算法中,將圖中的庫所和遷移都統(tǒng)一歸為節(jié)點,由于B-路徑是找到一個構(gòu)件內(nèi)部的所有路徑,因此可以將兩個構(gòu)件間的庫所和遷移先忽略掉,而只考慮一個構(gòu)件內(nèi)部的所有庫所和遷移,以下給出B-路徑的生成算法:
(1)首先定義兩個數(shù)組set1和set2,并使之為空,初始化節(jié)點p0使之為初始節(jié)點,初始化節(jié)點pf使之為終止節(jié)點(終止節(jié)點可不唯一)。
(2)從初始節(jié)點p0向下搜索,找到所有與p0直接相連的邊((p0→pi),(p0→pj)…),同時修改數(shù)組set1,將每條路徑分別存入數(shù)組set1中(即將路徑(p0→pi),(p0→pj)…分別存入數(shù)組中的每個元素)。當(dāng)數(shù)組set1不為空時,作:
①對數(shù)組set1中的每條路徑Ci(i=0,1…)進(jìn)行檢查,如果路徑Ci的最后一個節(jié)點為pf,則將Ci存入數(shù)組set2中,同時將其從數(shù)組set1中刪除。否則作:
②對數(shù)組set1中的每條路徑Ci(i=0,1…)進(jìn)行檢查,如果路徑Ci中某個節(jié)點出現(xiàn)的次數(shù)大于等于3,則將其從數(shù)組set1中刪除。否則作:
③沿路徑Ci中的最后一個節(jié)點pk繼續(xù)向下搜索,找出與pk節(jié)點直接相連的路徑((pk→pr),(pk→pq)…),并將其與路徑Ci進(jìn)行連接,即將與pk節(jié)點直接相連的路徑連接到Ci的后面((p0…→pk→pr)(p0…→pk→pq)…),并分別存入數(shù)組set1中,同時將Ci從set1中刪除。
(3)算法結(jié)束
最終,數(shù)組set2中存放的所有路徑就是一個構(gòu)件內(nèi)部的所有B-路徑,然后根據(jù)得到的該構(gòu)件內(nèi)部的B-路徑設(shè)計測試用例的輸入和預(yù)期輸出。
根據(jù)B-路徑生成算法,可以分別得到C/S結(jié)構(gòu)中Client構(gòu)件和Server構(gòu)件的B-路徑,從而完成對兩個構(gòu)件內(nèi)部的測試。以下給出了Client構(gòu)件中的B-路徑:
①client.p0-client.open-client.p1-client.request-client.p2-client.result-client.p1-client.close-client.p4-client.§2-client.p5
②client.p0-client.§1-client.p3
③client.p0-client.open-client.p1-client.close-client.p4-client.§2-client.p5
根據(jù)路徑覆蓋準(zhǔn)則,覆蓋以上三條路徑就可以完成對Client構(gòu)件內(nèi)部進(jìn)行的測試,同理可以得到Server構(gòu)件的內(nèi)部行為路徑。
3.2 C-路徑生成算法
B-路徑生成算法只能對構(gòu)件內(nèi)部進(jìn)行測試,當(dāng)需要對兩個構(gòu)件間進(jìn)行測試時,就需要找到連接兩個構(gòu)件間的所有路徑,即找到BG圖中的C-路徑。以下給出BG圖中C-路徑生成算法的基本思想。
首先找到連接兩個構(gòu)件的所有庫所(遷移),對找到的每一個庫所(遷移)向前搜索直到找到它的前一個庫所為止,對找到的每一個庫所(遷移)向后搜索直到找到它的后一個庫所為止,同時記錄所經(jīng)過的路徑,即可生成BG圖中的所有C-路徑。以下給出了C/S結(jié)構(gòu)中的所有C-路徑:
①client.p0-client.open-p101-server.open-server.p1
②client.p1-client.request-p102-server.request-server.p2
③server.p2-server.result-p104-client.result-client.p1
④client.p1-client.close-p103-server.close-server.p4
將以上兩種算法生成的路徑結(jié)合在一起,就可以完成對C/S結(jié)構(gòu)的集成測試,根據(jù)定義的測試覆蓋準(zhǔn)則,生成整個BG圖中的所有測試路徑,然后根據(jù)生成的測試路徑,設(shè)計測試用例的輸入和預(yù)期的輸出結(jié)果,從而完成對C/S結(jié)構(gòu)的測試工作。
實例證明這種基于軟件體系結(jié)構(gòu)的測試路徑生成方法在生成測試路徑上是可行的,下一步工作將主要集中在根據(jù)生成的測試路徑設(shè)計相應(yīng)的測試用例。
參考文獻(xiàn)
[1] SHAW M, GARLAN D. Software architecture:perspectives on an emerging discipline.Prentice Hall,1996
[2] 梅宏, 申峻嶸.軟件體系結(jié)構(gòu)研究進(jìn)展[J].軟件學(xué)報, 2006,17(6):1257-1275.
[3] Jin Zhenyi, OFFUTT J. Deriving tests from software architectures[C].12th International Symposium on Software Reliability Engineering,Hong Kong,2001:308-313.
[4] ROBERT A. A formal approach to software architecture. carnegie mellon university.CMU Technical Report CMUCS-97-144,1997(5).
[5] BERTOLINO A. Deriving test plans from architectural descriptions.In:ACM Proc.Int.Conf.on Software Engineering (ICSE2001),2000,6:220-229.
[6] ABDURAZIK A, Jin Zhenyi, OFFUTT A J, et al. Analyzing software architecture descriptions to generate systemlevel tests.http://www. ics.uci.edu/~djr/rosatea/attendees.html.
[7] DAVID R. Adequate testing of component based software. department of information and computer science, University of California,Irvine,Technical Report UCI-ICS-97-34, 1997,8.
[8] ROZENBERG G, THIAGARAJAN P S. Petri nets: Basic notions, structure and behavior. Lecture Notes in Computer Science,224. Berlin: Springer, 1986:585-668.
[9] Allen Robertand Garlan D. A case study in architectural modeling: The AEGIS System. In Proceedings of Eighth International Conference on Software Specification and Design (IWSSD-8),Paderborn,Germany, 1996(3).
