《軟件測試技術》課件第9章_第1頁
《軟件測試技術》課件第9章_第2頁
《軟件測試技術》課件第9章_第3頁
《軟件測試技術》課件第9章_第4頁
《軟件測試技術》課件第9章_第5頁
已閱讀5頁,還剩97頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第9章面向對象軟件的測試9.1面向對象技術對軟件測試的影響9.2面向對象軟件測試的層次9.3面向對象的單元測試9.4面向對象的集成測試9.5面向對象的系統測試9.6面向對象的測試和傳統測試的比較9.7本章小結9.1面向對象技術對軟件測試的影響

面向對象技術因為能夠解決傳統程序設計語言存在的問題,自提出以后,一度成為研究熱點。事實上,采用面向對象技術減少了不少錯誤的發生,對于提高軟件質量起到了很大的作用。

面向對象程序設計的核心思想就是對客觀事物的抽象。它是從眾多現實生活中感性的事物中抽取事物共同本質的特征,舍棄其非本質的特征。它是將這些本質的特性映射到現實概念類,并且模擬現實的事物,通過對類進行實體化而產生對象的過程。面向對象就是一個由具體到抽象,再由抽象到具體的過程。在這個過程中,把數據及其操作作為一個整體對待,數據本身不能被外部過程直接存取。其具體過程如圖9-1-1所示。圖9-1-1面向對象程序的設計示意圖9.1.1封裝對測試的影響

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

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

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

1.重構代碼

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

2.建立MockObject

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

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

建立測試類,在測試類中建立被測試對象時,通過方法覆蓋的方式返回模擬對象。測試用對象調用的方法來模仿對象的方法。這里也利用了面向對象設計中的多態和動態綁定的技術。測試代碼如下:執行測試中,被測試對象Lottery所調用的LotteryOdds對象被MockLotteryOdds代替。其調用的方法均為MockLotteryOdds所實現的方法。

通過建立MockObject的方法,可以實現對對象的模擬,在面向對象的單元測試、集成測試中都會用到該技術。在實際的應用中,遇到HttpRequest、HttpServletRequest、JDBC中的ResultSet對象時,就需要建立較為復雜的MockObject了。現在有許多功能來幫助我們建立這些復雜的MockObject,如在Java陣營中主要的Mock測試工具有JMock、MockCreator、Mockrunner、EasyMock、MockMaker等,而在微軟的.Net陣營中主要是Nmock、.NetMock等。9.1.2信息隱藏對測試的影響

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

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

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

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

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

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,當然如果使用JUnit擴展包JUnitX,可以不必擔心這些問題。JUnitX提供測試私有和保護方法的單元測試工具,它建立在JUnit之上,其關鍵類JUnitx.framework.PrivateUseCase繼承了JUnit.framework.TestCase,所以JUnit提供的TestRunner可以直接運行基于PrivateUseCase的測試類。9.1.3繼承對測試的影響

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

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

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

/**

*超類完成加法和減法

*@authorAdministrator

*2008-7-22

*/

publicclassSuperClass{

/**

*加法運算

*@parama加數a*@paramb加數b

*@return返回a+b

*/

publicintop1(finalinta,finalintb){

returna+b;

}

/**

*減法運算

*@parama被減數a

*@paramb減數b

*@return返回a-b*/

publicintop2(finalinta,finalintb){

returna-b;

}

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

/**

*子類,其中擴展乘法運行,改寫了減法運算

*@authorAdministrator

*2008-7-22

*/

publicclassSubClassextendsSuperClass{

/**

*乘法運行

*@parama乘數a

*@paramb乘數b

*@return返回a*b

*/

publicfinalintop3(finalinta,finalintb){

returna*b;

}

/**

*減法運算*@paramb被減數a

*@parama減數b

*@return返回b-a

*/

publicintop2(finalinta,finalintb){

returnb-a;

}

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

importjunit.framework.TestCase;

importorg.junit.After;

importorg.junit.Assert;

importorg.junit.Before;

importorg.junit.Test;

publicclassSuperClassTestextendsTestCase{

SuperClasssuperclass;

@Before

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

importorg.junit.After;

importorg.junit.Assert;

importorg.junit.Before;

importorg.junit.Test;

publicclassSubClassTestextendsSuperClassTest{9.1.4多態和動態綁定對測試的影響

多態性和動態綁定(DynamicBinding)是面向對象的關鍵特性之一。多態性是指同一消息可以根據發生消息的對象不同而采取不同的處理方法,例如操作“move”,可以是自行車對象的行為,可以是飛機對象的行為,也可以是窗口對象的移動行為。多態的具體表現形式包括兩類:一是重載,它允許幾個函數有相同的名字,而所帶的參數類型、數量不同,在系統運行時自動選擇不同的實現方法;二是在類的繼承上進行方法覆蓋,即同樣的消息可以被送到一個父類和它的子類對象上,在不同的對象上對一個類的操作是可以完全不同的。面向對象程序設計中,利用這種多態來提高程序的抽象性,突出語言的繼承性。它大大提高了程序的抽象程度和簡潔性,更重要的是它最大限度地降低了類和程序模塊之間的耦合性,提高了類模塊的封閉性,使得它們不需了解對方的具體細節,就可以很好地共同工作。這個優點對程序的設計、開發和維護都有很大的好處。

但是多態使得系統在運行時能自動為給定的消息選擇合適的實現代碼,它所帶來的不確定性也使得傳統測試實踐中的靜態分析法遇到了不可逾越的障礙,同時它們也增加了系統運行中可能的執行路徑,加大了測試用例的選取難度和數量。這種不確定性和驟然增加的路徑組合給測試覆蓋率的滿足帶來了挑戰。面向對象技術提高了軟件系統的靈活性、一般性和生產率,同時也增加了軟件測試的難度和復雜性。面向對象的軟件測試作為面向對象軟件工程的重要過程,它同樣也要求用面向對象技術去測試,根據面向對象的特點,以對象為中心的軟件測試。

9.2面向對象軟件測試的層次

軟件測試層次是基于測試復雜性分解的思想,是軟件測試的一種基本模式。面向對象程序的結構不再是傳統的功能模塊結構,作為一個整體,原有的集成測試所要求的逐步將開發的模塊組裝在一起進行測試的方法已成為不可能。而且,面向對象軟件拋棄了傳統的開發模式,對每個開發階段都有不同以往的要求和結果,已經不可能用功能細化的觀點來檢測面向對象分析和設計的結果。因此,傳統的測試模型對面向對象軟件已經不再適用。在面向對象軟件測試中,繼承和聚合關系刻畫了類之間的內在層次,它們既是構造系統結構的基礎,也是構造測試結構的基礎。根據測試層次結構,面向對象軟件測試總體上呈現從單元級、集成級到系統級的分層測試結構。其根據測試層次結構確定相應的測試活動,并生成相應的層次。由于面向對象軟件從宏觀上來看是各個類之間的相互作用,可以將對類層的測試作為單元測試,而對于由類簇集成的模塊測試對應到集成測試,系統測試與傳統測試層相同。具體的層次關系如表9-2-1所示。

1.類測試

類測試又可以分為兩級:一是方法級測試,二是類級測試。兩者測試的重點有所不同。

方法級測試重點在于測試封裝在類中的每一個方法。這些方法關系到對類的數據成員所進行的操作。方法級測試可以采用傳統的模塊測試方法,但方法是封裝在類中,并通過向所在對象發消息來執行。它的執行與狀態有關,特別是在操作的多態性時,設計測試用例時要考慮設置對象的初態,并且要設計一些函數來觀察隱蔽的狀態值。測試方法主要是根據傳統的單元測試方法,即運用前面介紹的面向對象測試中的一些基于面向對象特點的技術。類級測試重點在于測試同一類中不同方法之間的交互關系。面向對象的類測試主要考察封裝在一個類中的方法和類的狀態行為。進行類測試時要把對象與其狀態結合起來,進行對象狀態行為的測試,因為工作過程中對象的狀態可能會被改變,而產生新的狀態。測試范圍主要是類定義之內的屬性和服務,以及有限的對外接口的部分。在類測試過程中,不能僅僅檢查輸入數據產生的結果是否與預期的吻合,還要考慮對象的狀態,整個過程應涉及對象的初態、輸入參數、輸出參數以及對象的終態。

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

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

1)基于類間協作關系的橫向測試

由系統的一個輸入事件作為激勵,對其觸發的一組類進行測試,執行相應的操作、消息處理路徑,最后終止于某一輸出事件。應用回歸測試對已測試過的類集再重新執行一次,以保證加入新類時不會產生意外的結果。

2)基于類間繼承關系的縱向測試

首先通過測試獨立類(指系統中已經測試正確的某類)來開始構造系統,在獨立類測試完成后,下一層繼承獨立類的類(稱為依賴類)被測試,這個依賴類層次的測試序列一直循環執行到構造完整個系統。

3.系統測試

系統測試是對所有程序和外部成員構成的整個系統進行整體測試,檢驗軟件和其他系統成員配合工作是否正確,另外,還包括了確認測試內容,以驗證軟件系統的正確性和性能指標等是否滿足需求規格說明書所制定的要求。它與傳統的系統測試一樣,可沿用傳統的系統測試方法。

在整個面向對象的軟件測試過程中,集成測試可與單元測試同時進行,以減少單元集成時出現的錯誤。對已經測試通過的單元,在集成測試或系統測試中,可能發現獨立測試沒有發現的錯誤。

Perry和Kaiser等通過研究weyuker的測試數據集充分性公理得出了以下幾個與面向對象程序有關的測試公理,在測試中我們應該予以遵守。

(1)反合成性公理:對程序的各個獨立部分單獨進行了充分的測試并不表明整個軟件得到了充分的測試。這是因為當這些獨立部分交互時會產生它們在隔離狀態下所不具備的新的分支。

(2)反分解性公理:對程序的整體進行了充分的測試并不表明程序的各個獨立部分都得到了充分的測試。這是因為這些獨立的部分有可能被用在其他的環境中,在這種情況下就需要在這種環境中對這個部分重新進行測試。

(3)反擴展性公理:對一個程序進行的充分性測試并不一定能使另一個相似的程序也得到充分的測試。這是因為兩個相似的程序可能會具有完全不同的實現。

9.3面向對象的單元測試

傳統軟件的基本構成單元為功能模塊,每個功能模塊一般能獨立地完成一個特定的功能。而在面向對象的軟件中,基本單元是封裝了數據和方法的類和對象。對象是類的實例,有自己的角色,并在系統中承擔特定的責任。對象有自己的生存周期和狀態,狀態可以演變。對象的功能是在信息的觸發下,實現對象中若干方法的合成以及與其他對象的合作。對象中的數據和方法是一個有機整體,面向對象的單元測試的類測試分兩個部分:一是以方法為單元,另一種是以類為單元。但無論是哪種級別,所設計的測試用例,建議都以測試類的形式來組織,避免針對同一類設計的測試用例過于分散。9.3.1以方法為單元

類的行為是通過其內部方法來表現的,方法可以看作傳統測試中的模塊。簡單地說,這種方法與傳統測試方法中的單元測試方法類似。因此,傳統針對模塊的設計測試案例的技術例如邏輯覆蓋、等價劃分、邊界值分析和錯誤推測等方法,仍然可以作為測試類中每個方法的主要技術。面向對象中為了提高方法的重用性,每個方法所實現的功能應盡量小,每個方法常常只由幾行代碼組成,控制比較簡單,因此測試用例的設計相對比較容易。基于方法的單元測試需要樁和驅動器測試方法。另外,封裝將數據、操作等集成在一個相對獨立的程序單元——類中,類中方法的執行離不開一定的對象環境。測試類中的任何一個方法都必須首先將這個類實例化。在具體的測試過程中,方法封裝在類中并通過向所在對象發消息來執行,它的執行與狀態有關。具體過程如圖9-3-1所示。因此在具體的測試設計過程中,應注意針對不同的狀態設計測試用例來測試類的成員方法。圖9-3-1面向對象的單元測試模型9.3.2以類為單元

面向對象軟件中,在保證單個方法功能正確的基礎上,還應該測試方法之間的協作關系。所以在類測試過程中還需要將整個類作為測試單元進行測試,用來測試某一公有方法與類中其他直接或間接調用的方法間的協作和交互情況,它類似于過程式語言中的集成測試。

以類為單元的測試方法可以沿用傳統的過程模型的集成測試方法。在這里的集成范圍被控制在測試類中方法間的協作交互。除此之外,在面向對象的單元測試中,還可以采用其他的測試方法,這里介紹基于狀態圖的類測試方法。對象狀態測試是面向對象軟件測試的重要部分,同傳統的控制流和數據流測試相比,它側重于對象的動態行為,這種動態行為依賴于對象的狀態。通過測試對象動態行為,我們能檢測出對象成員函數之間通過對象狀態進行交互時產生的錯誤。因為對象的狀態是通過對象數據成員的值反映出來的,所以檢查對象的狀態實際上就是跟蹤被監視對象數據成員的值的變化。如果某個方法執行后對象的狀態未能夠按預期的方法改變,則說明該方法中含有錯誤。下面分步來介紹基于狀態圖的類測試。

1.狀態轉移圖

類是面向對象程序的靜態部分,對象是動態部分。對象的行為主要決定于對象狀態和對象狀態的轉移。面向對象設計方法通常采用狀態轉移圖建立對象的動態行為模型。狀態轉移圖用于刻畫對象響應各種事件時狀態發生轉移的情況,圖中節點表示對象的某個可能狀態,節點之間的有向邊通常用“事件/動作”標出。狀態轉移圖中的節點代表對象的邏輯狀態,而非所有可能的實際狀態。如圖9-3-2的示例中,表示當對象處于狀態A時,若接收到事件event則執行相應的操作action且轉移到狀態B。因此,對象的狀態隨各種外來事件發生怎樣的變化,是考察對象行為的一個重要方面。其中A、B表示兩種狀態,event表示收到的事件。圖9-3-2對象—狀態轉移圖

2.測試方法

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

測試過程為:首先生成對象;接著向對象發送消息把對象狀態設置到測試實例指定的狀態;再發送消息調用對象的方法;最后檢查對象的狀態是否按預期的方式發生變化。

3.測試步驟

下面給出基于狀態轉移圖的類測試的主要步驟:

(1)依據設計文檔或者通過分析對象數據成員的取值情況,導出對象的邏輯狀態空間,得到被測試類的狀態轉移圖。

(2)給被測試的類加入用于設置和檢查對象狀態的新方法。

(3)對于狀態轉移圖中的每個狀態,確定該狀態是哪些方法的合法起始狀態,即在該狀態時,對象允許執行哪些操作。

(4)在每個狀態中,從類中方法的調用關系圖最下層開始,逐一測試類中的方法,測試每個方法時,根據對象當前狀態確定出對方法的執行路徑有特殊影響的參數值,將各種可能組合作為參數進行測試。

4.測試用例的生成

對于基于狀態的類測試方法可采用深度或廣度測試的方法先建立擴展樹,樹的節點表示狀態,邊表示狀態之間的轉移。根據樹中的一條路徑(從根節點到葉節點)來生成測試用例。如圖9-3-3所示,將通過轉移a到狀態S1,根據S1狀態按照廣度擴展建立擴展樹。圖9-3-3面向對象單元測試狀態轉移擴展樹的生成示意圖狀態及轉移擴展樹 9.4面向對象的集成測試

基于單元測試對成員函數行為正確性的保證,而集成測試卻只關注系統的結構和內部的相互作用。對較大規模軟件系統的集成測試更是一項復雜的系統工程。面向對象的集成測試的任務是檢測出哪些類相互作用時才會產生的錯誤。測試的對象以類簇為單位,包括基于類間協作關系的橫向測試和基于類間繼承關系的縱向測試。而面向對象的集成測試中,類簇中類與類之間關系較復雜,對面向對象程序的靜態表示,已不是一個樹型層次結構,而是一個錯綜復雜的網狀結構,這就決定了傳統的基于層次結構的集成測試策略已不適用于面向對象程序的集成測試。因此,需要研究適應面向對象程序特點的新的集成測試策略。下面介紹基于UML的集成測試、具有MM-路徑的集成和基于數據流的面向對象的集成測試方法。9.4.1基于UML的集成測試

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

協同圖顯示的是類自己的(部分)信息傳輸。在圖中反映了類直接方法的調用情況。類似于前面傳統集成所介紹的調用圖。由此,面向對象的協同圖也支持成對集成和相鄰集成的方法。下面以一個模型為例,在該模型中,我們需要測試一個鴨子的外賣店DuckStor,該店可以根據用戶要求制作duck并提供外送業務。但用戶下了訂單orderDuck后,根據用戶要求DuckStor可以createDuck,這里提供3種地方特產的鴨子,四川的、北京的、上海的,每種鴨子需要不同的配方,所以根據鴨子類型的不同createDirection。同時DuckStor還可以直接查詢配方getXXDirection。圖9-4-1就是多個類的協同關系圖。可以根據這些協同關系來設計集成測試的方案,其實質就是基于調用的集成,可以采用成對集成和相鄰集成的方法。圖9-4-1“鴨子的外賣店”類的協同關系圖

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

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

在傳統的軟件的MM-路徑測試中,我們通過消息來表示單元(模塊)之間的調用,采用模塊執行路徑取代完整的模塊。在面向對象的測試中也可以使用同樣的方法來表示由消息分開的各種方法執行序列。與傳統軟件一樣,方法也可能有多條內部執行路徑。MM-路徑從某個方法開始,當到達某個自己不發送任何消息的方法時結束。這就是消息的靜止點。

溫馨提示

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

評論

0/150

提交評論