《軟件測試技術(shù)》課件第9章_第1頁
《軟件測試技術(shù)》課件第9章_第2頁
《軟件測試技術(shù)》課件第9章_第3頁
《軟件測試技術(shù)》課件第9章_第4頁
《軟件測試技術(shù)》課件第9章_第5頁
已閱讀5頁,還剩97頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第9章面向?qū)ο筌浖臏y試9.1面向?qū)ο蠹夹g(shù)對(duì)軟件測試的影響9.2面向?qū)ο筌浖y試的層次9.3面向?qū)ο蟮膯卧獪y試9.4面向?qū)ο蟮募蓽y試9.5面向?qū)ο蟮南到y(tǒng)測試9.6面向?qū)ο蟮臏y試和傳統(tǒng)測試的比較9.7本章小結(jié)9.1面向?qū)ο蠹夹g(shù)對(duì)軟件測試的影響

面向?qū)ο蠹夹g(shù)因?yàn)槟軌蚪鉀Q傳統(tǒng)程序設(shè)計(jì)語言存在的問題,自提出以后,一度成為研究熱點(diǎn)。事實(shí)上,采用面向?qū)ο蠹夹g(shù)減少了不少錯(cuò)誤的發(fā)生,對(duì)于提高軟件質(zhì)量起到了很大的作用。

面向?qū)ο蟪绦蛟O(shè)計(jì)的核心思想就是對(duì)客觀事物的抽象。它是從眾多現(xiàn)實(shí)生活中感性的事物中抽取事物共同本質(zhì)的特征,舍棄其非本質(zhì)的特征。它是將這些本質(zhì)的特性映射到現(xiàn)實(shí)概念類,并且模擬現(xiàn)實(shí)的事物,通過對(duì)類進(jìn)行實(shí)體化而產(chǎn)生對(duì)象的過程。面向?qū)ο缶褪且粋€(gè)由具體到抽象,再由抽象到具體的過程。在這個(gè)過程中,把數(shù)據(jù)及其操作作為一個(gè)整體對(duì)待,數(shù)據(jù)本身不能被外部過程直接存取。其具體過程如圖9-1-1所示。圖9-1-1面向?qū)ο蟪绦虻脑O(shè)計(jì)示意圖9.1.1封裝對(duì)測試的影響

封裝是類的基本特性之一。它將一個(gè)對(duì)象的各個(gè)部分聚集在一個(gè)邏輯單元內(nèi)。封裝將類的所有數(shù)據(jù)和操作作為一個(gè)整體對(duì)待,數(shù)據(jù)本身不能被外部過程直接存取,促進(jìn)了程序的模塊化,并在一定程度上簡化了類的使用,避免了不合理的操作,并能有效地阻止錯(cuò)誤的擴(kuò)散。但同時(shí),它們也給程序的測試帶來了一定的問題。封裝將數(shù)據(jù)、操作等集成在一個(gè)相對(duì)獨(dú)立的程序單元——類中,類中方法的執(zhí)行離不開一定的對(duì)象環(huán)境。測試類中的任何一個(gè)方法都必須首先將這個(gè)類實(shí)例化。因此,測試用例的設(shè)計(jì)與其他測試的不同之處就是在測試設(shè)計(jì)中對(duì)樁模塊的設(shè)計(jì)有所不同。傳統(tǒng)測試中的樁模塊是模擬函數(shù),在面向?qū)ο蟮臏y試設(shè)計(jì)中,則是通過類的實(shí)體對(duì)象來訪問其屬性和方法。另外,對(duì)于具體的訪問與對(duì)象的狀態(tài)相關(guān)。因此,在測試用例的設(shè)計(jì)過程中還需要考慮對(duì)象的狀態(tài)。在面向?qū)ο蟮臏y試中,如果樁僅僅單一地模擬類中的方法,已經(jīng)不適用了。在面向?qū)ο蟮臏y試中對(duì)樁設(shè)計(jì)時(shí),樁模擬的不再是傳統(tǒng)測試中的函數(shù),而是模仿對(duì)象(MockObject)。例如,要單元測試一個(gè)使用HttpRequest的對(duì)象,測試時(shí)需要啟動(dòng)Web服務(wù)器,構(gòu)造Request實(shí)例并填入所需要的值,測試完后需要停止Web服務(wù)器,這一系列過程可能很麻煩。模仿對(duì)象提供了解決這一困難的方法。模仿對(duì)象符合實(shí)際對(duì)象的接口,但需要有足夠的代碼來“欺騙”測試對(duì)象并跟蹤其行為。

模仿對(duì)象給樁設(shè)計(jì)提出一個(gè)解決方案:MockObject擁有與被測對(duì)象的“合作者”完全一致的接口,在測試中作為“合作者”被傳遞給被測對(duì)象。當(dāng)被測對(duì)象調(diào)用合作者時(shí),MockObject根據(jù)測試者的意愿改變某些狀態(tài)或返回期望的結(jié)果,以檢查被測程序是否按照所期望的邏輯進(jìn)行工作,達(dá)到測試的目的。或者說,MockObject作為“仿真器”出現(xiàn)在測試用例中,對(duì)被測對(duì)象進(jìn)行“欺騙”和跟蹤。而只要MockObject的行為與被測對(duì)象所期望的一致,就不會(huì)對(duì)被測對(duì)象產(chǎn)生任何影響。這種模式對(duì)于許多情況都非常有效,但模仿對(duì)象有時(shí)不能被傳遞到正在測試的對(duì)象。而設(shè)計(jì)該對(duì)象是為了創(chuàng)建、查找或獲得其合作者。具體的做法以Java為例的單元測試來簡單說明。首先要進(jìn)行測試一個(gè)計(jì)算贏得抽獎(jiǎng)的幾率的程序,例如,如果從1到50中的數(shù)字中抽取6個(gè)數(shù)字來作為中獎(jiǎng)號(hào)碼,那么共有(50×49×48×46×45)/(1×2×3×4×5×6)個(gè)可能的中獎(jiǎng)號(hào)碼。所以中獎(jiǎng)的幾率為1/1890700。一般情況從n個(gè)數(shù)字中抽取k個(gè)數(shù)字,那么會(huì)有(n×(n-1)×(n-2)×…×(n-k))/(1×2×3×…×k)種可能。

下面通過程序來實(shí)現(xiàn),在該程序中由兩個(gè)類來實(shí)現(xiàn),一個(gè)接收界面數(shù)據(jù)并輸出結(jié)果,另一個(gè)計(jì)算幾率?,F(xiàn)在需要測試接收界面數(shù)據(jù)并輸出結(jié)果的類,代碼如下。下面我們需要測試類中的方法print(),在該方法中涉及到類LotteryOdds,程序通過類LotteryOdds來計(jì)算幾率。那么我們需要設(shè)置樁模塊。這里的樁模塊就需要建立MockObject來模擬LotteryOdds。具體過程為:首先將創(chuàng)建代碼抽取出工廠方法,由工廠方法來完成創(chuàng)建LotteryOdds對(duì)象,在測試子類中覆蓋該工廠方法,通過該覆蓋的工廠方法創(chuàng)建模仿對(duì)象;然后調(diào)用覆蓋的工廠方法來創(chuàng)建對(duì)象,那么創(chuàng)建的就是模仿對(duì)象,而不再是原LotteryOdds對(duì)象。這樣就可以完成單元測試了。具體步驟如下。

1.重構(gòu)代碼

重構(gòu)是一種代碼更改,它使原始功能保持不變,但更改了代碼設(shè)計(jì),使它變得更清晰、更有效且更易于測試。在本例中,重構(gòu)的主要工作就是將產(chǎn)生LotteryOdds的過程獨(dú)立處理成為類的方法之一。重構(gòu)后的代碼如下:

2.建立MockObject

建立類來模擬LotteryOdds類,可以直接繼承LotteryOdds類。這里我們建立私有類,這樣可以將該MockObject類直接放到測試用例類中,使得MockObject對(duì)象是針對(duì)單一的測試用例來設(shè)計(jì),并可以進(jìn)一步簡化MockObject的設(shè)計(jì)。具體的實(shí)現(xiàn)代碼如下:

3.建立TestCase,通過覆蓋的方法返回模仿對(duì)象

建立測試類,在測試類中建立被測試對(duì)象時(shí),通過方法覆蓋的方式返回模擬對(duì)象。測試用對(duì)象調(diào)用的方法來模仿對(duì)象的方法。這里也利用了面向?qū)ο笤O(shè)計(jì)中的多態(tài)和動(dòng)態(tài)綁定的技術(shù)。測試代碼如下:執(zhí)行測試中,被測試對(duì)象Lottery所調(diào)用的LotteryOdds對(duì)象被MockLotteryOdds代替。其調(diào)用的方法均為MockLotteryOdds所實(shí)現(xiàn)的方法。

通過建立MockObject的方法,可以實(shí)現(xiàn)對(duì)對(duì)象的模擬,在面向?qū)ο蟮膯卧獪y試、集成測試中都會(huì)用到該技術(shù)。在實(shí)際的應(yīng)用中,遇到HttpRequest、HttpServletRequest、JDBC中的ResultSet對(duì)象時(shí),就需要建立較為復(fù)雜的MockObject了?,F(xiàn)在有許多功能來幫助我們建立這些復(fù)雜的MockObject,如在Java陣營中主要的Mock測試工具有JMock、MockCreator、Mockrunner、EasyMock、MockMaker等,而在微軟的.Net陣營中主要是Nmock、.NetMock等。9.1.2信息隱藏對(duì)測試的影響

在封裝的基礎(chǔ)上,為了進(jìn)一步保證類的數(shù)據(jù)、操作的安全性,在面向?qū)ο蟮脑O(shè)計(jì)中又引入了信息隱藏技術(shù)。信息隱藏是指只讓用戶知道那些確保用戶正確使用一個(gè)對(duì)象所必需的信息,其他信息對(duì)用戶來說則被隱藏起來。對(duì)于面向?qū)ο蟮脑O(shè)計(jì)中共有的屬性和方法是可以訪問的,而私有的和受保護(hù)的屬性和方法,其訪問卻是受到限制的。這樣一來,對(duì)于面向?qū)ο蟮臏y試,信息隱藏帶來的主要問題則是對(duì)象狀態(tài)的觀察問題。由于信息隱藏機(jī)制的存在,類的內(nèi)部對(duì)外界來說是“不可見”的,其屬性和狀態(tài)只能通過類自身的方法或函數(shù)來獲得。這就給測試用例(尤其是預(yù)期結(jié)果)的生成帶來了一定的困難。為了能夠觀察到這些屬性和狀態(tài),以確定程序執(zhí)行的結(jié)果是否正確,在測試時(shí)可以采用以下技術(shù)來跳過信息隱藏,獲取類的屬性和狀態(tài)。

(1)修改被測試類,通過增加操作向測試者提供對(duì)象的屬性,但是這種方法是強(qiáng)制的,同時(shí)也不能確定引入的操作與類中原有的操作是否重名。

(2)在一個(gè)繼承類中定義新操作,該類繼承于測試類,并且只是用于協(xié)助測試,這個(gè)操作將獲取測試類的屬性。如果類的某些屬性不能為子類所訪問也是無用的,例如Java語言的私有屬性。

(3)某些語言通過引入一些機(jī)制來打破封裝,例如C++語言的friendsmembers。在Java中可以運(yùn)用其反射機(jī)制來實(shí)現(xiàn)。如測試中也可以通過getDeclaredMethods()來獲取所有的方法,包括私有方法。選擇解決方法的基本原則就是采用盡量不改變被測試類且能夠獲取屬性的最簡單的方法。方法(1)的缺點(diǎn)在于需要修改被測試類,方法(2)的缺點(diǎn)在于所要編寫的代碼量較多,方法(3)較可取。下面我們以Java程序?yàn)槔瑏碚f明方法(3)的用法。

在本例中,要測試對(duì)私有方法和私有屬性的訪問。下面是要測試的代碼類Unit,在示例代碼中,有兩個(gè)私有方法,一個(gè)是帶參數(shù)的,另外一個(gè)是不帶參數(shù)的。另外包含一個(gè)屬性,并建立set和get方法來訪問類的屬性。在設(shè)計(jì)測試用例時(shí),為了獲取類中的方法并運(yùn)行它,可以通過Java獲取類方法后,通過反射機(jī)制來訪問。在測試用例的設(shè)計(jì)中,重點(diǎn)用到getDeclaredMethods()方法來獲取類的所有方法,用getDeclaredFields()來獲取類的所有屬性,這包括公有、私有及包含成員。可以通過反射機(jī)制調(diào)用invoke()來調(diào)用對(duì)象的方法。對(duì)于屬性而言,還是不能直接訪問私有屬性,而需要通過set和get方法來訪問。具體的測試用例如下。下面的測試用例中,對(duì)私有方法getData()和getData(finalinti)進(jìn)行了測試,還對(duì)私有屬性myField的狀態(tài)變化進(jìn)行了相應(yīng)的測試。

importjava.lang.reflect.Field;

importjava.lang.reflect.Method;

importorg.junit.After;

importorg.junit.Before;

importorg.junit.Test;

importjunit.framework.Assert;

publicclassHideInforTest{

privateHideInforc;

privatefinalMethodmethods[]=HideInfor.class.getDeclaredMethods();

privatefinalFieldfield[]=HideInfor.class.getDeclaredFields();

@Before

publicvoidsetUp()throwsException{

c=newHideInfor(10);

c.setMyField(20);

}

@Test

publicvoidtestGetData()throwsException{

for(inti=0;i<methods.length;++i){

if(methods[i].getName().equals("getData")){}在本例中,使用了JUnit,當(dāng)然如果使用JUnit擴(kuò)展包JUnitX,可以不必?fù)?dān)心這些問題。JUnitX提供測試私有和保護(hù)方法的單元測試工具,它建立在JUnit之上,其關(guān)鍵類JUnitx.framework.PrivateUseCase繼承了JUnit.framework.TestCase,所以JUnit提供的TestRunner可以直接運(yùn)行基于PrivateUseCase的測試類。9.1.3繼承對(duì)測試的影響

繼承是面向?qū)ο笤O(shè)計(jì)中的另一重要特性。繼承性表達(dá)了類與類之間的關(guān)系,一個(gè)類可以定義為另一個(gè)類的擴(kuò)充或受限。繼承性是自動(dòng)地共享類、子類和對(duì)象中的方法和數(shù)據(jù)的機(jī)制。每個(gè)對(duì)象都是某個(gè)類的實(shí)例,一個(gè)系統(tǒng)中類對(duì)象是各自封閉的。如果沒有繼承機(jī)制,則類、對(duì)象中的數(shù)據(jù)和方法就可能出現(xiàn)大量重復(fù)。繼承使用已有的定義作為建立新定義的基礎(chǔ),它由三種基本機(jī)制(擴(kuò)展、覆蓋、特例化)來實(shí)現(xiàn)。擴(kuò)展是子類自動(dòng)包含超類的特征;覆蓋是子類中的方法與超類中的方法有相同的名字和消息參數(shù),接口相同,但方法的實(shí)現(xiàn)通常不同;特例化是子類中特有的方法和實(shí)例變量。繼承又可分為單繼承和多繼承等。在具體的實(shí)現(xiàn)中,繼承的種類可以分為單重繼承和多重繼承。不同的開發(fā)語言支持的繼承方式有所不同,如Java僅支持單繼承,而C++則支持多繼承。

繼承有利于代碼的復(fù)用,但也有些不足,主要體現(xiàn)在兩個(gè)方面:一是繼承提供機(jī)制,使得超類的BUG進(jìn)一步被帶到其子類;二是基于繼承的代碼的重用可能會(huì)導(dǎo)致維修困難,這是主要的設(shè)計(jì)質(zhì)量問題。實(shí)踐證明,繼承運(yùn)用得當(dāng),正確使用繼承的設(shè)計(jì)對(duì)類的測試是有利的。從繼承的不足可以看出,測試變得更加重要了,但對(duì)于測試來說,繼承卻增加了測試的復(fù)雜性。這當(dāng)然主要是針對(duì)子類的測試,它不但要求那些子類新定義或重新定義的方法要得到測試,被子類繼承的超類方法也往往要在子類的環(huán)境中重新測試,同時(shí),繼承使源代碼變得難于理解。一個(gè)深層次的最底層的子類可能只有一兩行代碼,但卻繼承了上百種特征。多重繼承會(huì)顯著地增加派生類的復(fù)雜程度,導(dǎo)致一些難以發(fā)現(xiàn)的隱含錯(cuò)誤。

在對(duì)子類進(jìn)行測試時(shí)需要將超類的特征也包含在內(nèi),因此可以將測試狀態(tài)空間分為兩個(gè)部分,被繼承的超類的狀態(tài)空間和由子類定義或重新定義的狀態(tài)空間,這兩部分之間是正交的關(guān)系。將這兩部分合而為一(展平),生成的平坦的狀態(tài)模型是對(duì)子類進(jìn)行狀態(tài)測試的依據(jù)。在測試過程中,雖然繼承帶來了許多復(fù)雜性,但是針對(duì)繼承自超類的方法、屬性,依然可以利用繼承特性進(jìn)行測試用例的復(fù)用,以提高測試的效率。下面我們通過一個(gè)實(shí)例來說明。本案例中,要測試兩個(gè)類:SuperClass和SubClass。其中SubClass由SuperClass派生,SuperClass為超類,SubClass為子類,圖9-1-2為其類圖。SuperClass完成整數(shù)加法和減法兩個(gè)運(yùn)算,SubClass在超類的基礎(chǔ)上增加整數(shù)的乘法運(yùn)算。圖9-1-2SuperClass和SubClass類圖在測試時(shí)首先可以針對(duì)超類SuperClass進(jìn)行測試,建立相應(yīng)的測試用例類。接下來再進(jìn)行子類SubClass的測試。在對(duì)SubClass測試時(shí),由于SubClass繼承了SuperClass的方法op1(),所以在建立SubClass的測試用例類,都可以繼承SuperClass的測試用例類。但是在SubClass的具體實(shí)現(xiàn)中其覆蓋了超類的方法op2(),所以在SubClass測試用例類中也要覆蓋超類測試用例類中對(duì)方法op2()的測試方法。其繼承關(guān)系如圖9-1-3所示。圖9-1-3超類子類及測試類UML類圖關(guān)系下面是超類SuperClass的代碼實(shí)現(xiàn),在SuperClass中包含兩個(gè)方法op1()和op2(),這些方法分別實(shí)現(xiàn)了加法和減法運(yùn)算。

/**

*超類完成加法和減法

*@authorAdministrator

*2008-7-22

*/

publicclassSuperClass{

/**

*加法運(yùn)算

*@parama加數(shù)a*@paramb加數(shù)b

*@return返回a+b

*/

publicintop1(finalinta,finalintb){

returna+b;

}

/**

*減法運(yùn)算

*@parama被減數(shù)a

*@paramb減數(shù)b

*@return返回a-b*/

publicintop2(finalinta,finalintb){

returna-b;

}

}子類SubClass在實(shí)現(xiàn)時(shí)繼承自SuperClass,它在超類的基礎(chǔ)上實(shí)現(xiàn)了方法op3(),完成乘法功能,并且對(duì)超類SuperClass的方法op2()進(jìn)行覆蓋,將在超類中對(duì)方法op2()進(jìn)行改寫,也同樣實(shí)現(xiàn)了減法,但交換了減數(shù)和被減數(shù)的位置。具體代碼如下:

/**

*子類,其中擴(kuò)展乘法運(yùn)行,改寫了減法運(yùn)算

*@authorAdministrator

*2008-7-22

*/

publicclassSubClassextendsSuperClass{

/**

*乘法運(yùn)行

*@parama乘數(shù)a

*@paramb乘數(shù)b

*@return返回a*b

*/

publicfinalintop3(finalinta,finalintb){

returna*b;

}

/**

*減法運(yùn)算*@paramb被減數(shù)a

*@parama減數(shù)b

*@return返回b-a

*/

publicintop2(finalinta,finalintb){

returnb-a;

}

}接下來開始建立測試類。首先測試超類,在測試中,分別對(duì)方法op1()和op2()進(jìn)行功能測試。該代碼仍然在JUnit下的TestCase,具體代碼如下:

importjunit.framework.TestCase;

importorg.junit.After;

importorg.junit.Assert;

importorg.junit.Before;

importorg.junit.Test;

publicclassSuperClassTestextendsTestCase{

SuperClasssuperclass;

@Before

接下來測試SubClass,子類SubClass的測試用例類建立繼承自SuperClass的測試類SuperClassTest,并在其基礎(chǔ)上,增加了對(duì)方法op3()的測試,以及改寫對(duì)方法op2()的測試。為了復(fù)用SuperClass的測試用例,在創(chuàng)建子類SubClass對(duì)象時(shí),還需要對(duì)超類SuperClassTest繼承來的對(duì)象SuperClass進(jìn)行賦值操作。具體的代碼如下:

importorg.junit.After;

importorg.junit.Assert;

importorg.junit.Before;

importorg.junit.Test;

publicclassSubClassTestextendsSuperClassTest{9.1.4多態(tài)和動(dòng)態(tài)綁定對(duì)測試的影響

多態(tài)性和動(dòng)態(tài)綁定(DynamicBinding)是面向?qū)ο蟮年P(guān)鍵特性之一。多態(tài)性是指同一消息可以根據(jù)發(fā)生消息的對(duì)象不同而采取不同的處理方法,例如操作“move”,可以是自行車對(duì)象的行為,可以是飛機(jī)對(duì)象的行為,也可以是窗口對(duì)象的移動(dòng)行為。多態(tài)的具體表現(xiàn)形式包括兩類:一是重載,它允許幾個(gè)函數(shù)有相同的名字,而所帶的參數(shù)類型、數(shù)量不同,在系統(tǒng)運(yùn)行時(shí)自動(dòng)選擇不同的實(shí)現(xiàn)方法;二是在類的繼承上進(jìn)行方法覆蓋,即同樣的消息可以被送到一個(gè)父類和它的子類對(duì)象上,在不同的對(duì)象上對(duì)一個(gè)類的操作是可以完全不同的。面向?qū)ο蟪绦蛟O(shè)計(jì)中,利用這種多態(tài)來提高程序的抽象性,突出語言的繼承性。它大大提高了程序的抽象程度和簡潔性,更重要的是它最大限度地降低了類和程序模塊之間的耦合性,提高了類模塊的封閉性,使得它們不需了解對(duì)方的具體細(xì)節(jié),就可以很好地共同工作。這個(gè)優(yōu)點(diǎn)對(duì)程序的設(shè)計(jì)、開發(fā)和維護(hù)都有很大的好處。

但是多態(tài)使得系統(tǒng)在運(yùn)行時(shí)能自動(dòng)為給定的消息選擇合適的實(shí)現(xiàn)代碼,它所帶來的不確定性也使得傳統(tǒng)測試實(shí)踐中的靜態(tài)分析法遇到了不可逾越的障礙,同時(shí)它們也增加了系統(tǒng)運(yùn)行中可能的執(zhí)行路徑,加大了測試用例的選取難度和數(shù)量。這種不確定性和驟然增加的路徑組合給測試覆蓋率的滿足帶來了挑戰(zhàn)。面向?qū)ο蠹夹g(shù)提高了軟件系統(tǒng)的靈活性、一般性和生產(chǎn)率,同時(shí)也增加了軟件測試的難度和復(fù)雜性。面向?qū)ο蟮能浖y試作為面向?qū)ο筌浖こ痰闹匾^程,它同樣也要求用面向?qū)ο蠹夹g(shù)去測試,根據(jù)面向?qū)ο蟮奶攸c(diǎn),以對(duì)象為中心的軟件測試。

9.2面向?qū)ο筌浖y試的層次

軟件測試層次是基于測試復(fù)雜性分解的思想,是軟件測試的一種基本模式。面向?qū)ο蟪绦虻慕Y(jié)構(gòu)不再是傳統(tǒng)的功能模塊結(jié)構(gòu),作為一個(gè)整體,原有的集成測試所要求的逐步將開發(fā)的模塊組裝在一起進(jìn)行測試的方法已成為不可能。而且,面向?qū)ο筌浖仐壛藗鹘y(tǒng)的開發(fā)模式,對(duì)每個(gè)開發(fā)階段都有不同以往的要求和結(jié)果,已經(jīng)不可能用功能細(xì)化的觀點(diǎn)來檢測面向?qū)ο蠓治龊驮O(shè)計(jì)的結(jié)果。因此,傳統(tǒng)的測試模型對(duì)面向?qū)ο筌浖呀?jīng)不再適用。在面向?qū)ο筌浖y試中,繼承和聚合關(guān)系刻畫了類之間的內(nèi)在層次,它們既是構(gòu)造系統(tǒng)結(jié)構(gòu)的基礎(chǔ),也是構(gòu)造測試結(jié)構(gòu)的基礎(chǔ)。根據(jù)測試層次結(jié)構(gòu),面向?qū)ο筌浖y試總體上呈現(xiàn)從單元級(jí)、集成級(jí)到系統(tǒng)級(jí)的分層測試結(jié)構(gòu)。其根據(jù)測試層次結(jié)構(gòu)確定相應(yīng)的測試活動(dòng),并生成相應(yīng)的層次。由于面向?qū)ο筌浖暮暧^上來看是各個(gè)類之間的相互作用,可以將對(duì)類層的測試作為單元測試,而對(duì)于由類簇集成的模塊測試對(duì)應(yīng)到集成測試,系統(tǒng)測試與傳統(tǒng)測試層相同。具體的層次關(guān)系如表9-2-1所示。

1.類測試

類測試又可以分為兩級(jí):一是方法級(jí)測試,二是類級(jí)測試。兩者測試的重點(diǎn)有所不同。

方法級(jí)測試重點(diǎn)在于測試封裝在類中的每一個(gè)方法。這些方法關(guān)系到對(duì)類的數(shù)據(jù)成員所進(jìn)行的操作。方法級(jí)測試可以采用傳統(tǒng)的模塊測試方法,但方法是封裝在類中,并通過向所在對(duì)象發(fā)消息來執(zhí)行。它的執(zhí)行與狀態(tài)有關(guān),特別是在操作的多態(tài)性時(shí),設(shè)計(jì)測試用例時(shí)要考慮設(shè)置對(duì)象的初態(tài),并且要設(shè)計(jì)一些函數(shù)來觀察隱蔽的狀態(tài)值。測試方法主要是根據(jù)傳統(tǒng)的單元測試方法,即運(yùn)用前面介紹的面向?qū)ο鬁y試中的一些基于面向?qū)ο筇攸c(diǎn)的技術(shù)。類級(jí)測試重點(diǎn)在于測試同一類中不同方法之間的交互關(guān)系。面向?qū)ο蟮念悳y試主要考察封裝在一個(gè)類中的方法和類的狀態(tài)行為。進(jìn)行類測試時(shí)要把對(duì)象與其狀態(tài)結(jié)合起來,進(jìn)行對(duì)象狀態(tài)行為的測試,因?yàn)楣ぷ鬟^程中對(duì)象的狀態(tài)可能會(huì)被改變,而產(chǎn)生新的狀態(tài)。測試范圍主要是類定義之內(nèi)的屬性和服務(wù),以及有限的對(duì)外接口的部分。在類測試過程中,不能僅僅檢查輸入數(shù)據(jù)產(chǎn)生的結(jié)果是否與預(yù)期的吻合,還要考慮對(duì)象的狀態(tài),整個(gè)過程應(yīng)涉及對(duì)象的初態(tài)、輸入?yún)?shù)、輸出參數(shù)以及對(duì)象的終態(tài)。

2.類簇測試(集成測試)

我們把一組相互有影響的類看作一個(gè)整體,稱為類簇。類簇測試主要根據(jù)系統(tǒng)中相關(guān)類的層次關(guān)系,檢查類之間的相互作用的正確性,即檢查各相關(guān)類之間消息連接的合法性、子類的繼承性與父類的一致性、動(dòng)態(tài)綁定執(zhí)行的正確性、類簇協(xié)同完成系統(tǒng)功能的正確性等等。其測試有兩種不同策略,即基于類間協(xié)作關(guān)系的橫向測試和基于類間繼承關(guān)系的縱向測試。

1)基于類間協(xié)作關(guān)系的橫向測試

由系統(tǒng)的一個(gè)輸入事件作為激勵(lì),對(duì)其觸發(fā)的一組類進(jìn)行測試,執(zhí)行相應(yīng)的操作、消息處理路徑,最后終止于某一輸出事件。應(yīng)用回歸測試對(duì)已測試過的類集再重新執(zhí)行一次,以保證加入新類時(shí)不會(huì)產(chǎn)生意外的結(jié)果。

2)基于類間繼承關(guān)系的縱向測試

首先通過測試獨(dú)立類(指系統(tǒng)中已經(jīng)測試正確的某類)來開始構(gòu)造系統(tǒng),在獨(dú)立類測試完成后,下一層繼承獨(dú)立類的類(稱為依賴類)被測試,這個(gè)依賴類層次的測試序列一直循環(huán)執(zhí)行到構(gòu)造完整個(gè)系統(tǒng)。

3.系統(tǒng)測試

系統(tǒng)測試是對(duì)所有程序和外部成員構(gòu)成的整個(gè)系統(tǒng)進(jìn)行整體測試,檢驗(yàn)軟件和其他系統(tǒng)成員配合工作是否正確,另外,還包括了確認(rèn)測試內(nèi)容,以驗(yàn)證軟件系統(tǒng)的正確性和性能指標(biāo)等是否滿足需求規(guī)格說明書所制定的要求。它與傳統(tǒng)的系統(tǒng)測試一樣,可沿用傳統(tǒng)的系統(tǒng)測試方法。

在整個(gè)面向?qū)ο蟮能浖y試過程中,集成測試可與單元測試同時(shí)進(jìn)行,以減少單元集成時(shí)出現(xiàn)的錯(cuò)誤。對(duì)已經(jīng)測試通過的單元,在集成測試或系統(tǒng)測試中,可能發(fā)現(xiàn)獨(dú)立測試沒有發(fā)現(xiàn)的錯(cuò)誤。

Perry和Kaiser等通過研究weyuker的測試數(shù)據(jù)集充分性公理得出了以下幾個(gè)與面向?qū)ο蟪绦蛴嘘P(guān)的測試公理,在測試中我們應(yīng)該予以遵守。

(1)反合成性公理:對(duì)程序的各個(gè)獨(dú)立部分單獨(dú)進(jìn)行了充分的測試并不表明整個(gè)軟件得到了充分的測試。這是因?yàn)楫?dāng)這些獨(dú)立部分交互時(shí)會(huì)產(chǎn)生它們?cè)诟綦x狀態(tài)下所不具備的新的分支。

(2)反分解性公理:對(duì)程序的整體進(jìn)行了充分的測試并不表明程序的各個(gè)獨(dú)立部分都得到了充分的測試。這是因?yàn)檫@些獨(dú)立的部分有可能被用在其他的環(huán)境中,在這種情況下就需要在這種環(huán)境中對(duì)這個(gè)部分重新進(jìn)行測試。

(3)反擴(kuò)展性公理:對(duì)一個(gè)程序進(jìn)行的充分性測試并不一定能使另一個(gè)相似的程序也得到充分的測試。這是因?yàn)閮蓚€(gè)相似的程序可能會(huì)具有完全不同的實(shí)現(xiàn)。

9.3面向?qū)ο蟮膯卧獪y試

傳統(tǒng)軟件的基本構(gòu)成單元為功能模塊,每個(gè)功能模塊一般能獨(dú)立地完成一個(gè)特定的功能。而在面向?qū)ο蟮能浖?,基本單元是封裝了數(shù)據(jù)和方法的類和對(duì)象。對(duì)象是類的實(shí)例,有自己的角色,并在系統(tǒng)中承擔(dān)特定的責(zé)任。對(duì)象有自己的生存周期和狀態(tài),狀態(tài)可以演變。對(duì)象的功能是在信息的觸發(fā)下,實(shí)現(xiàn)對(duì)象中若干方法的合成以及與其他對(duì)象的合作。對(duì)象中的數(shù)據(jù)和方法是一個(gè)有機(jī)整體,面向?qū)ο蟮膯卧獪y試的類測試分兩個(gè)部分:一是以方法為單元,另一種是以類為單元。但無論是哪種級(jí)別,所設(shè)計(jì)的測試用例,建議都以測試類的形式來組織,避免針對(duì)同一類設(shè)計(jì)的測試用例過于分散。9.3.1以方法為單元

類的行為是通過其內(nèi)部方法來表現(xiàn)的,方法可以看作傳統(tǒng)測試中的模塊。簡單地說,這種方法與傳統(tǒng)測試方法中的單元測試方法類似。因此,傳統(tǒng)針對(duì)模塊的設(shè)計(jì)測試案例的技術(shù)例如邏輯覆蓋、等價(jià)劃分、邊界值分析和錯(cuò)誤推測等方法,仍然可以作為測試類中每個(gè)方法的主要技術(shù)。面向?qū)ο笾袨榱颂岣叻椒ǖ闹赜眯?,每個(gè)方法所實(shí)現(xiàn)的功能應(yīng)盡量小,每個(gè)方法常常只由幾行代碼組成,控制比較簡單,因此測試用例的設(shè)計(jì)相對(duì)比較容易。基于方法的單元測試需要樁和驅(qū)動(dòng)器測試方法。另外,封裝將數(shù)據(jù)、操作等集成在一個(gè)相對(duì)獨(dú)立的程序單元——類中,類中方法的執(zhí)行離不開一定的對(duì)象環(huán)境。測試類中的任何一個(gè)方法都必須首先將這個(gè)類實(shí)例化。在具體的測試過程中,方法封裝在類中并通過向所在對(duì)象發(fā)消息來執(zhí)行,它的執(zhí)行與狀態(tài)有關(guān)。具體過程如圖9-3-1所示。因此在具體的測試設(shè)計(jì)過程中,應(yīng)注意針對(duì)不同的狀態(tài)設(shè)計(jì)測試用例來測試類的成員方法。圖9-3-1面向?qū)ο蟮膯卧獪y試模型9.3.2以類為單元

面向?qū)ο筌浖校诒WC單個(gè)方法功能正確的基礎(chǔ)上,還應(yīng)該測試方法之間的協(xié)作關(guān)系。所以在類測試過程中還需要將整個(gè)類作為測試單元進(jìn)行測試,用來測試某一公有方法與類中其他直接或間接調(diào)用的方法間的協(xié)作和交互情況,它類似于過程式語言中的集成測試。

以類為單元的測試方法可以沿用傳統(tǒng)的過程模型的集成測試方法。在這里的集成范圍被控制在測試類中方法間的協(xié)作交互。除此之外,在面向?qū)ο蟮膯卧獪y試中,還可以采用其他的測試方法,這里介紹基于狀態(tài)圖的類測試方法。對(duì)象狀態(tài)測試是面向?qū)ο筌浖y試的重要部分,同傳統(tǒng)的控制流和數(shù)據(jù)流測試相比,它側(cè)重于對(duì)象的動(dòng)態(tài)行為,這種動(dòng)態(tài)行為依賴于對(duì)象的狀態(tài)。通過測試對(duì)象動(dòng)態(tài)行為,我們能檢測出對(duì)象成員函數(shù)之間通過對(duì)象狀態(tài)進(jìn)行交互時(shí)產(chǎn)生的錯(cuò)誤。因?yàn)閷?duì)象的狀態(tài)是通過對(duì)象數(shù)據(jù)成員的值反映出來的,所以檢查對(duì)象的狀態(tài)實(shí)際上就是跟蹤被監(jiān)視對(duì)象數(shù)據(jù)成員的值的變化。如果某個(gè)方法執(zhí)行后對(duì)象的狀態(tài)未能夠按預(yù)期的方法改變,則說明該方法中含有錯(cuò)誤。下面分步來介紹基于狀態(tài)圖的類測試。

1.狀態(tài)轉(zhuǎn)移圖

類是面向?qū)ο蟪绦虻撵o態(tài)部分,對(duì)象是動(dòng)態(tài)部分。對(duì)象的行為主要決定于對(duì)象狀態(tài)和對(duì)象狀態(tài)的轉(zhuǎn)移。面向?qū)ο笤O(shè)計(jì)方法通常采用狀態(tài)轉(zhuǎn)移圖建立對(duì)象的動(dòng)態(tài)行為模型。狀態(tài)轉(zhuǎn)移圖用于刻畫對(duì)象響應(yīng)各種事件時(shí)狀態(tài)發(fā)生轉(zhuǎn)移的情況,圖中節(jié)點(diǎn)表示對(duì)象的某個(gè)可能狀態(tài),節(jié)點(diǎn)之間的有向邊通常用“事件/動(dòng)作”標(biāo)出。狀態(tài)轉(zhuǎn)移圖中的節(jié)點(diǎn)代表對(duì)象的邏輯狀態(tài),而非所有可能的實(shí)際狀態(tài)。如圖9-3-2的示例中,表示當(dāng)對(duì)象處于狀態(tài)A時(shí),若接收到事件event則執(zhí)行相應(yīng)的操作action且轉(zhuǎn)移到狀態(tài)B。因此,對(duì)象的狀態(tài)隨各種外來事件發(fā)生怎樣的變化,是考察對(duì)象行為的一個(gè)重要方面。其中A、B表示兩種狀態(tài),event表示收到的事件。圖9-3-2對(duì)象—狀態(tài)轉(zhuǎn)移圖

2.測試方法

基于狀態(tài)的測試是通過檢查對(duì)象的狀態(tài)在執(zhí)行某個(gè)方法后是否會(huì)轉(zhuǎn)移到預(yù)期狀態(tài)的一種測試技術(shù)。使用該技術(shù)能夠檢驗(yàn)類中的方法是否正確地交互,即類中的方法是否能通過對(duì)象的狀態(tài)正確地通信。 理論上講,對(duì)象的狀態(tài)空間是對(duì)象所有數(shù)據(jù)成員定義域的笛卡爾乘積。當(dāng)對(duì)象含有多個(gè)數(shù)據(jù)成員時(shí),對(duì)對(duì)象所有的可能狀態(tài)進(jìn)行測試是不現(xiàn)實(shí)的,這就需要對(duì)對(duì)象的狀態(tài)空間進(jìn)行簡化,同時(shí)又不失對(duì)數(shù)據(jù)成員取值的“覆蓋面”。簡化對(duì)象狀態(tài)空間的基本思想類似于黑盒測試中常用的等價(jià)類劃分法。依據(jù)軟件設(shè)計(jì)規(guī)范或分析程序源代碼,可以從對(duì)象數(shù)據(jù)成員的取值域中找到一些特殊值和一般性的區(qū)間。特殊值是設(shè)計(jì)規(guī)范里說明有特殊意義、在程序源代碼中邏輯上需特殊處理的取值。位于一般性區(qū)間中的值不需要區(qū)別各個(gè)值的差別,在邏輯上以同樣方式處理。 進(jìn)行基于狀態(tài)的測試時(shí),首先要對(duì)受測試的類進(jìn)行擴(kuò)充定義,即增加一些用于設(shè)置和檢查對(duì)象狀態(tài)的方法。通常是對(duì)每一個(gè)數(shù)據(jù)成員設(shè)置一個(gè)改變其取值的方法。另一項(xiàng)重要工作是編寫作為主控的測試驅(qū)動(dòng)程序,如果被測試的對(duì)象在執(zhí)行某個(gè)方法時(shí)還要調(diào)用其他對(duì)象的方法,則需編寫樁程序代替其他對(duì)象的方法。

測試過程為:首先生成對(duì)象;接著向?qū)ο蟀l(fā)送消息把對(duì)象狀態(tài)設(shè)置到測試實(shí)例指定的狀態(tài);再發(fā)送消息調(diào)用對(duì)象的方法;最后檢查對(duì)象的狀態(tài)是否按預(yù)期的方式發(fā)生變化。

3.測試步驟

下面給出基于狀態(tài)轉(zhuǎn)移圖的類測試的主要步驟:

(1)依據(jù)設(shè)計(jì)文檔或者通過分析對(duì)象數(shù)據(jù)成員的取值情況,導(dǎo)出對(duì)象的邏輯狀態(tài)空間,得到被測試類的狀態(tài)轉(zhuǎn)移圖。

(2)給被測試的類加入用于設(shè)置和檢查對(duì)象狀態(tài)的新方法。

(3)對(duì)于狀態(tài)轉(zhuǎn)移圖中的每個(gè)狀態(tài),確定該狀態(tài)是哪些方法的合法起始狀態(tài),即在該狀態(tài)時(shí),對(duì)象允許執(zhí)行哪些操作。

(4)在每個(gè)狀態(tài)中,從類中方法的調(diào)用關(guān)系圖最下層開始,逐一測試類中的方法,測試每個(gè)方法時(shí),根據(jù)對(duì)象當(dāng)前狀態(tài)確定出對(duì)方法的執(zhí)行路徑有特殊影響的參數(shù)值,將各種可能組合作為參數(shù)進(jìn)行測試。

4.測試用例的生成

對(duì)于基于狀態(tài)的類測試方法可采用深度或廣度測試的方法先建立擴(kuò)展樹,樹的節(jié)點(diǎn)表示狀態(tài),邊表示狀態(tài)之間的轉(zhuǎn)移。根據(jù)樹中的一條路徑(從根節(jié)點(diǎn)到葉節(jié)點(diǎn))來生成測試用例。如圖9-3-3所示,將通過轉(zhuǎn)移a到狀態(tài)S1,根據(jù)S1狀態(tài)按照廣度擴(kuò)展建立擴(kuò)展樹。圖9-3-3面向?qū)ο髥卧獪y試狀態(tài)轉(zhuǎn)移擴(kuò)展樹的生成示意圖狀態(tài)及轉(zhuǎn)移擴(kuò)展樹 9.4面向?qū)ο蟮募蓽y試

基于單元測試對(duì)成員函數(shù)行為正確性的保證,而集成測試卻只關(guān)注系統(tǒng)的結(jié)構(gòu)和內(nèi)部的相互作用。對(duì)較大規(guī)模軟件系統(tǒng)的集成測試更是一項(xiàng)復(fù)雜的系統(tǒng)工程。面向?qū)ο蟮募蓽y試的任務(wù)是檢測出哪些類相互作用時(shí)才會(huì)產(chǎn)生的錯(cuò)誤。測試的對(duì)象以類簇為單位,包括基于類間協(xié)作關(guān)系的橫向測試和基于類間繼承關(guān)系的縱向測試。而面向?qū)ο蟮募蓽y試中,類簇中類與類之間關(guān)系較復(fù)雜,對(duì)面向?qū)ο蟪绦虻撵o態(tài)表示,已不是一個(gè)樹型層次結(jié)構(gòu),而是一個(gè)錯(cuò)綜復(fù)雜的網(wǎng)狀結(jié)構(gòu),這就決定了傳統(tǒng)的基于層次結(jié)構(gòu)的集成測試策略已不適用于面向?qū)ο蟪绦虻募蓽y試。因此,需要研究適應(yīng)面向?qū)ο蟪绦蛱攸c(diǎn)的新的集成測試策略。下面介紹基于UML的集成測試、具有MM-路徑的集成和基于數(shù)據(jù)流的面向?qū)ο蟮募蓽y試方法。9.4.1基于UML的集成測試

1.基于UML協(xié)同圖的分解的集成測試方法

協(xié)同圖顯示的是類自己的(部分)信息傳輸。在圖中反映了類直接方法的調(diào)用情況。類似于前面?zhèn)鹘y(tǒng)集成所介紹的調(diào)用圖。由此,面向?qū)ο蟮膮f(xié)同圖也支持成對(duì)集成和相鄰集成的方法。下面以一個(gè)模型為例,在該模型中,我們需要測試一個(gè)鴨子的外賣店DuckStor,該店可以根據(jù)用戶要求制作duck并提供外送業(yè)務(wù)。但用戶下了訂單orderDuck后,根據(jù)用戶要求DuckStor可以createDuck,這里提供3種地方特產(chǎn)的鴨子,四川的、北京的、上海的,每種鴨子需要不同的配方,所以根據(jù)鴨子類型的不同createDirection。同時(shí)DuckStor還可以直接查詢配方getXXDirection。圖9-4-1就是多個(gè)類的協(xié)同關(guān)系圖??梢愿鶕?jù)這些協(xié)同關(guān)系來設(shè)計(jì)集成測試的方案,其實(shí)質(zhì)就是基于調(diào)用的集成,可以采用成對(duì)集成和相鄰集成的方法。圖9-4-1“鴨子的外賣店”類的協(xié)同關(guān)系圖

2.基于UML序列圖分解的集成測試方法

UML順序圖是按時(shí)間的順序來描述對(duì)象之間交互的模型。序列圖主要用于按照交互發(fā)生的一系列順序,顯示對(duì)象之間的這些交互。開發(fā)者一般認(rèn)為序列圖只對(duì)他們有意義,然而,業(yè)務(wù)人員會(huì)發(fā)現(xiàn),序列圖顯示不同的業(yè)務(wù)對(duì)象如何交互,對(duì)于交流當(dāng)前業(yè)務(wù)如何進(jìn)行很有用。序列圖對(duì)于測試人員也非常有用。在順序圖中,如果消息message1出現(xiàn)在消息message2的上面,則message1一定在message2之前被發(fā)送。在測試中引入U(xiǎn)ML順序圖,我們只需要按照序列圖表示的消息順序來測試對(duì)象類之間的交互即可。對(duì)于每一個(gè)類與其他類,它們之間的對(duì)象與對(duì)象的調(diào)用路徑都可以用順序圖表現(xiàn)出來,只要我們的測試用例覆蓋了該類與其他類調(diào)用的所有順序圖,我們就認(rèn)為用這些測試用例集完全覆蓋了該類與類的集成關(guān)系,也就是說該類與其他類之間進(jìn)行集成的接口已經(jīng)完全被測試過了。對(duì)于基于順序圖的測試,其測試用例基本是根據(jù)順序圖來設(shè)計(jì)的。順序圖在實(shí)質(zhì)上就是按照一定前置條件和后置條件排列好的交互系列。在這個(gè)交互系列中,只有前置條件和后置條件都為真時(shí)才能進(jìn)行下一步交互。只要前置條件或后置條件有一個(gè)為假,則交互都不能順利進(jìn)行或者說交互不正確。對(duì)于前置條件和后置條件為假的交互,我們可以統(tǒng)一按相同的方法來對(duì)待。同樣以鴨子的外賣店DuckStor為例,序列圖如圖9-4-2所示。從其序列圖中我們可以看出,通過測試驅(qū)動(dòng)模塊下達(dá)Order后DuckStor的活動(dòng)序列。圖9-4-2中僅表示出了訂購一只四川鴨子的過程,其消息的傳遞過程都在圖中表示出來了。在集成測試時(shí)可以根據(jù)這個(gè)消息的傳遞過程來選擇集成的對(duì)象。另外還可以看出鴨子切片的活動(dòng)在鴨子生產(chǎn)出來后才能進(jìn)行。也就是說,制作鴨子的活動(dòng)是切鴨子活動(dòng)的前提條件。圖9-4-2“鴨子的外賣店”活動(dòng)序列9.4.2基于MM-路徑的集成測試

在傳統(tǒng)的軟件的MM-路徑測試中,我們通過消息來表示單元(模塊)之間的調(diào)用,采用模塊執(zhí)行路徑取代完整的模塊。在面向?qū)ο蟮臏y試中也可以使用同樣的方法來表示由消息分開的各種方法執(zhí)行序列。與傳統(tǒng)軟件一樣,方法也可能有多條內(nèi)部執(zhí)行路徑。MM-路徑從某個(gè)方法開始,當(dāng)?shù)竭_(dá)某個(gè)自己不發(fā)送任何消息的方法時(shí)結(jié)束。這就是消息的靜止點(diǎn)。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論