一 摘要(Abstract)
[摘要]
面向?qū)ο蠹夹g(shù)在軟件工程中的推廣使用,使得傳統(tǒng)的測試技術(shù)和方法受到了極大的沖擊。對面向?qū)ο蠹夹g(shù)所引入的新特點(diǎn),傳統(tǒng)的測試技術(shù)已經(jīng)無法有效的進(jìn)行測試。對面向?qū)ο筌浖臏y試,測試策略或方法都需要出現(xiàn)相應(yīng)的變革或更新。
就此,本文結(jié)合傳統(tǒng)的測試技術(shù),針對面向?qū)ο蠹夹g(shù)新特性在測試中所引發(fā)的問題,提出一種測試模型。首先,以軟件工程中面向?qū)ο筌浖_發(fā)模式為參考,分別在面向?qū)ο蠓治觯嫦驅(qū)ο笤O(shè)計(jì),面向?qū)ο缶幊倘齻€階段,依據(jù)各階段的地位,作用,實(shí)現(xiàn)目標(biāo),具體闡述測試目的和應(yīng)該注意的測試點(diǎn)。其次,依照傳統(tǒng)的三個測試步驟:單元測試,集成測試,系統(tǒng)測試,借鑒傳統(tǒng)測試方法有用的部分,論述如何有效的對面向?qū)ο筌浖M(jìn)行測試。最后,完成ZXM10收發(fā)臺軟件測試。
[Abstract]
Since the Object-Oriented technology has been used in software engineering, the traditional test methods meet the big challenge. For the features of Object-Orient software, the traditional test methods can not be applied directly to Object-Orient software efficiently as used. To Object-Orient software, the test strategy and test methods must be adapted.
At this point, this thesis advises how to test Object-Oriented software, in a new test model, especially for those issues present to Object-Oriented software test, basing on some traditional test strategy and methods. Firstly, consult the Object-Oriented development procedure; discuss what should pay more attention during testing at the step of OOA, OOD, and OOP. Then, discuss how to do unit test, integrate test and system test of Object-Oriented software. At last, show you what I have done to the Object-Oriented software of send-receive message platform of ZXM10.
二 關(guān)鍵詞(Key Words)
軟件測試(Software test) 面向?qū)ο螅∣O: Object-Oriented)
三 引言(Introduction)
用戶使用低質(zhì)量的軟件,在運(yùn)行過程中會產(chǎn)生各種各樣的問題,可能帶來不同程度的嚴(yán)重后果,輕者影響系統(tǒng)的正常工作,重者造成事故,損失生命財(cái)產(chǎn)。軟件測試是保證軟件質(zhì)量的最重要的手段。什么是軟件測試?1983年IEEE定義為:使用人工或自動手段來運(yùn)行或測定某個系統(tǒng)的過程,其目的在于檢驗(yàn)它是否滿足規(guī)定的需求或是弄清預(yù)期結(jié)果與實(shí)際結(jié)果之間的差別。
現(xiàn)代的軟件開發(fā)工程是將整個軟件開發(fā)過程明確的劃分為幾個階段(參見[6]的論述),將復(fù)雜問題具體按階段加以解決。這樣,在軟件的整個開發(fā)過程中,可以對每一階段提出若干明確的監(jiān)控點(diǎn),作為各階段目標(biāo)實(shí)現(xiàn)的檢驗(yàn)標(biāo)準(zhǔn),從而提高開發(fā)過程的可見度和保證開發(fā)過程的正確性。經(jīng)驗(yàn)證明,軟件的質(zhì)量不僅是體現(xiàn)在程序的正確性上,它和編碼以前所做的需求分析,軟件設(shè)計(jì)密切相關(guān)。軟件使用中出現(xiàn)的錯誤,不一定是編程人員在編碼階段引入的,很可能在程序設(shè)計(jì),甚而需求分析時就埋下了禍因。這時,對錯誤的糾正往往不能通過可能會誘發(fā)更多錯誤的簡單的修修補(bǔ)補(bǔ),而必須追溯到軟件開發(fā)的最初階段。這無疑增大了軟件的開發(fā)費(fèi)用。因此,為了保證軟件的質(zhì)量,我們應(yīng)該著眼于整個軟件生存期,特別是著眼于編碼以前的各開發(fā)階段的工作。這樣,軟件測試的概念和實(shí)施范圍必須擴(kuò)充,應(yīng)該包括在整個開發(fā)各階段的復(fù)查、評估和檢測。由此,廣義的軟件測試實(shí)際是由確認(rèn)、驗(yàn)證、測試三個方面組成(注:本文對后面用廣義測試概念處不另加標(biāo)識):
確認(rèn):是評估將要開發(fā)的軟件產(chǎn)品是否是正確無誤、可行和有價值的。比如,將要開發(fā)的軟件是否會滿足用戶提出的要求,是否能在將來的實(shí)際使用環(huán)境中正確穩(wěn)定的運(yùn)行,是否存在隱患等。這里包含了對用戶需求滿足程度的評價。確認(rèn)意味著確保一個待開發(fā)軟件是正確無誤的,是對軟件開發(fā)構(gòu)想的檢測。
驗(yàn)證:是檢測軟件開發(fā)的每個階段、每個步驟的結(jié)果是否正確無誤,是否與軟件開發(fā)各階段的要求或期望的結(jié)果相一致。驗(yàn)證意味著確保軟件是會正確無誤的實(shí)現(xiàn)軟件的需求,開發(fā)過程是沿著正確的方向在進(jìn)行。
測試:與狹隘的測試概念統(tǒng)一。通常是經(jīng)過單元測試、集成測試、系統(tǒng)測試三個環(huán)節(jié)。
在整個軟件生存期(參見[6]中的劃分),確認(rèn)、驗(yàn)證、測試分別有其側(cè)重的階段。確認(rèn)主要體現(xiàn)在計(jì)劃階段、需求分析階段、也會出現(xiàn)在測試階段;驗(yàn)證主要體現(xiàn)在設(shè)計(jì)階段和編碼階段;測試主要體現(xiàn)在編碼階段和測試階段。事實(shí)上,確認(rèn)、驗(yàn)證、測試是相輔相成的。確認(rèn)無疑會產(chǎn)生驗(yàn)證和測試的標(biāo)準(zhǔn),而驗(yàn)證和測試通常又會幫助完成一些確認(rèn),特別是在系統(tǒng)測試階段。
面向?qū)ο蠹夹g(shù)是一種全新的軟件開發(fā)技術(shù),正逐漸代替被廣泛使用的面向過程開發(fā)方法,被看成是解決軟件危機(jī)的新興技術(shù)。面向?qū)ο蠹夹g(shù)產(chǎn)生更好的系統(tǒng)結(jié)構(gòu),更規(guī)范的編程風(fēng)格,極大的優(yōu)化了數(shù)據(jù)使用的安全性,提高了程序代碼的重用,一些人就此認(rèn)為面向?qū)ο蠹夹g(shù)開發(fā)出的程序無需進(jìn)行測試。應(yīng)該看到,盡管面向?qū)ο蠹夹g(shù)的基本思想保證了軟件應(yīng)該有更高的質(zhì)量,但實(shí)際情況卻并非如此,因?yàn)闊o論采用什么樣的編程技術(shù),編程人員的錯誤都是不可避免的,而且由于面向?qū)ο蠹夹g(shù)開發(fā)的軟件代碼重用率高,更需要嚴(yán)格測試,避免錯誤的繁衍。因此,軟件測試并沒有面向?qū)ο缶幊痰呐d起而喪失掉它的重要性。
從1982年在美國北卡羅來納大學(xué)召開首次軟件測試的正式技術(shù)會議至今,軟件測試?yán)碚撗杆侔l(fā)展,并相應(yīng)出現(xiàn)了各種軟件測試方法,使軟件測試技術(shù)得到極大的提高。然而,一度實(shí)踐證明行之有效的軟件測試對面向?qū)ο蠹夹g(shù)開發(fā)的軟件多少顯得有些力不從心。尤其是面向?qū)ο蠹夹g(shù)所獨(dú)有的多態(tài),繼承,封裝等新特點(diǎn),產(chǎn)生了傳統(tǒng)語言設(shè)計(jì)所不存在的錯誤可能性,或者使得傳統(tǒng)軟件測試中的重點(diǎn)不再顯得突出,或者使原來測試經(jīng)驗(yàn)認(rèn)為和實(shí)踐證明的次要方面成為了主要問題。例如:
在傳統(tǒng)的面向過程程序中,對于函數(shù)
y=Function(x);
你只需要考慮一個函數(shù)(Function())的行為特點(diǎn),而在面向?qū)ο蟪绦蛑?,你不得不同時考慮基類函數(shù)(Base::Function())的行為和繼承類函數(shù)(Derived::Function())的行為。
面向?qū)ο蟪绦虻慕Y(jié)構(gòu)不再是傳統(tǒng)的功能模塊結(jié)構(gòu),作為一個整體,原有集成測試所要求的逐步將開發(fā)的模塊搭建在一起進(jìn)行測試的方法已成為不可能。而且,面向?qū)ο筌浖仐壛藗鹘y(tǒng)的開發(fā)模式,對每個開發(fā)階段都有不同以往的要求和結(jié)果,已經(jīng)不可能用功能細(xì)化的觀點(diǎn)來檢測面向?qū)ο蠓治龊驮O(shè)計(jì)的結(jié)果。因此,傳統(tǒng)的測試模型對面向?qū)ο筌浖呀?jīng)不再適用。針對面向?qū)ο筌浖拈_發(fā)特點(diǎn),應(yīng)該有一種新的測試模型。
四 面向?qū)ο鬁y試模型(Object-Orient Test Model)
面向?qū)ο蟮拈_發(fā)模型突破了傳統(tǒng)的瀑布模型,將開發(fā)分為面向?qū)ο蠓治觯∣OA),面向?qū)ο笤O(shè)計(jì)(OOD),和面向?qū)ο缶幊蹋∣OP)三個階段。分析階段產(chǎn)生整個問題空間的抽象描述,在此基礎(chǔ)上,進(jìn)一步歸納出適用于面向?qū)ο缶幊陶Z言的類和類結(jié)構(gòu),最后形成代碼。由于面向?qū)ο蟮奶攸c(diǎn),采用這種開發(fā)模型能有效的將分析設(shè)計(jì)的文本或圖表代碼化,不斷適應(yīng)用戶需求的變動。針對這種開發(fā)模型,結(jié)合傳統(tǒng)的測試步驟的劃分,本文建議一種整個軟件開發(fā)過程中不斷測試的測試模型,使開發(fā)階段的測試與編碼完成后的單元測試、集成測試、系統(tǒng)測試成為一個整體。測試模型如下圖所示:
0 面向?qū)ο缶幊?div style="height:15px;">
OOA Test:面向?qū)ο蠓治龅臏y試 OOD Test:面向?qū)ο笤O(shè)計(jì)的測試
OOP Test:面向?qū)ο缶幊痰臏y試 OO Unit Test:面向?qū)ο髥卧獪y試
OO Integrate Test:面向?qū)ο蠹蓽y試 OO System Test:面向?qū)ο笙到y(tǒng)測試
OOA Test和OOD Test 是對分析結(jié)果和設(shè)計(jì)結(jié)果的測試,主要是對分析設(shè)計(jì)產(chǎn)生的文本進(jìn)行,是軟件開發(fā)前期的關(guān)鍵性測試。OOP Test主要針對編程風(fēng)格和程序代碼實(shí)現(xiàn)進(jìn)行測試,其主要的測試內(nèi)容在面向?qū)ο髥卧獪y試和面向?qū)ο蠹蓽y試中體現(xiàn)。面向?qū)ο髥卧獪y試是對程序內(nèi)部具體單一的功能模塊的測試,如果程序是用C++語言實(shí)現(xiàn),主要就是對類成員函數(shù)的測試。面向?qū)ο髥卧獪y試是進(jìn)行面向?qū)ο蠹蓽y試的基礎(chǔ)。面向?qū)ο蠹蓽y試主要對系統(tǒng)內(nèi)部的相互服務(wù)進(jìn)行測試,如成員函數(shù)間的相互作用,類間的消息傳遞等。面向?qū)ο蠹蓽y試不但要基于面向?qū)ο髥卧獪y試,更要參見OOD或OOD Test結(jié)果(詳見后敘述)。面向?qū)ο笙到y(tǒng)測試是基于面向?qū)ο蠹蓽y試的最后階段的測試,主要以用戶需求為測試標(biāo)準(zhǔn),需要借鑒OOA或OOA Test結(jié)果。
盡管上述各階段的測試構(gòu)成一相互作用的整體,但其測試的主體、方向和方法各有不同,且為敘述的方便,本文接下來將從OOA,OOD,OOP,單元測試,集成測試,系統(tǒng)測試六個方面分別介紹對面向?qū)ο筌浖臏y試。
對由OOA,OOP,OOD這三個開發(fā)階段所構(gòu)成的開發(fā)模型、各階段應(yīng)該完成的目標(biāo)以及結(jié)果報(bào)告的形式等詳細(xì)介紹,已經(jīng)超出本文內(nèi)容,請參見[1]。
五 面向?qū)ο蠓治龅臏y試(OOA Test)
傳統(tǒng)的面向過程分析是一個功能分解的過程,是把一個系統(tǒng)看成可以分解的功能的集合。這種傳統(tǒng)的功能分解分析法的著眼點(diǎn)在于一個系統(tǒng)需要什么樣的信息處理方法和過程,以過程的抽象來對待系統(tǒng)的需要。而面向?qū)ο蠓治觯∣OA)是"把E-R圖和語義網(wǎng)絡(luò)模型,即信息造型中的概念,與面向?qū)ο蟪绦蛟O(shè)計(jì)語言中的重要概念結(jié)合在一起而形成的分析方法"(參見[1]),最后通常是得到問題空間的圖表的形式描述。
OOA直接映射問題空間,全面的將問題空間中實(shí)現(xiàn)功能的現(xiàn)實(shí)抽象化。將問題空間中的實(shí)例抽象為對象(不同于C++中的對象概念),用對象的結(jié)構(gòu)反映問題空間的復(fù)雜實(shí)例和復(fù)雜關(guān)系,用屬性和服務(wù)表示實(shí)例的特性和行為。對一個系統(tǒng)而言,與傳統(tǒng)分析方法產(chǎn)生的結(jié)果相反,行為是相對穩(wěn)定的,結(jié)構(gòu)是相對不穩(wěn)定的,這更充分反映了現(xiàn)實(shí)的特性。OOA的結(jié)果是為后面階段類的選定和實(shí)現(xiàn),類層次結(jié)構(gòu)的組織和實(shí)現(xiàn)提供平臺。因此,OOA對問題空間分析抽象的不完整,最終會影響軟件的功能實(shí)現(xiàn),導(dǎo)致軟件開發(fā)后期大量可避免的修補(bǔ)工作;而一些冗余的對象或結(jié)構(gòu)會影響類的選定、程序的整體結(jié)構(gòu)或增加程序員不必要的工作量。因此,本文對OOA的測試重點(diǎn)在其完整性和冗余性。
盡管OOA的測試是一個不可分割的系統(tǒng)過程,為敘述的方便,鑒于[2]中Coad方法所提出的OOA實(shí)現(xiàn)步驟,對OOA階段的測試劃分為以下五個方面:
☆ 對認(rèn)定的對象的測試
☆ 對認(rèn)定的結(jié)構(gòu)的測試
☆ 對認(rèn)定的主題的測試
☆ 對定義的屬性和實(shí)例關(guān)聯(lián)的測試
☆ 對定義的服務(wù)和消息關(guān)聯(lián)的測試
對象、結(jié)構(gòu)、主題等在OOA結(jié)果中的位置,參見下圖:
1 對認(rèn)定的對象的測試:
OOA中認(rèn)定的對象是對問題空間中的結(jié)構(gòu),其他系統(tǒng),設(shè)備,被記憶的事件,系統(tǒng)涉及的人員等實(shí)際實(shí)例的抽象(參見[2])。對它的測試可以從如下方面考慮:
1.1 認(rèn)定的對象是否全面,是否問題空間中所有涉及到的實(shí)例都反映在認(rèn)定的抽象對象中。
1.2 認(rèn)定的對象是否具有多個屬性。只有一個屬性的對象通常應(yīng)看成其他對象的屬性,而不是抽象為獨(dú)立的對象。
1.3 對認(rèn)定為同一對象的實(shí)例是否有共同的,區(qū)別于其他實(shí)例的共同屬性。
1.4 對認(rèn)定為同一對象的實(shí)例是否提供或需要相同的服務(wù),如果服務(wù)隨著不同的實(shí)例而變化,認(rèn)定的對象就需要分解或利用繼承性來分類表示。
1.5 如果系統(tǒng)沒有必要始終保持對象代表的實(shí)例的信息,提供或者得到關(guān)于它的服務(wù),認(rèn)定的對象也無必要。
1.6 認(rèn)定的對象的名稱應(yīng)該盡量準(zhǔn)確,適用。
2 對認(rèn)定的結(jié)構(gòu)的測試
在Coad方法中,認(rèn)定的結(jié)構(gòu)指的是多種對象的組織方式,用來反映問題空間中的復(fù)雜實(shí)例和復(fù)雜關(guān)系。認(rèn)定的結(jié)構(gòu)分為兩種:分類結(jié)構(gòu)和組裝結(jié)構(gòu)。分類結(jié)構(gòu)體現(xiàn)了問題空間中實(shí)例的一般與特殊的關(guān)系,組裝結(jié)構(gòu)體現(xiàn)了問題空間中實(shí)例整體與局部的關(guān)系。
2.1 對認(rèn)定的分類結(jié)構(gòu)的測試可從如下方面著手:
2.1.1 對于結(jié)構(gòu)中的一種對象,尤其是處于高層的對象,是否在問題空間中含有不同于下一層對象的特殊可能性,即是否能派生出下一層對象。
2.1.2 對于結(jié)構(gòu)中的一種對象,尤其是處于同一低層的對象,是否能抽象出在現(xiàn)實(shí)中有意義的更一般的上層對象。
2.1.3 對所有認(rèn)定的對象,是否能在問題空間內(nèi)向上層抽象出在現(xiàn)實(shí)中有意義的對象
2.1.4 高層的對象的特性是否完全體現(xiàn)下層的共性
2.1.5 低層的對象是否有高層特性基礎(chǔ)上的特殊性
2.2 對認(rèn)定的組裝結(jié)構(gòu)的測試從如下方面入手:
2.2.1 整體(對象)和部件(對象)的組裝關(guān)系是否符合現(xiàn)實(shí)的關(guān)系。
2.2.2 整體(對象)的部件(對象)是否在考慮的問題空間中有實(shí)際應(yīng)用。
2.2.3 整體(對象)中是否遺漏了反映在問題空間中有用的部件(對象)。
2.2.4 部件(對象)是否能夠在問題空間中組裝新的有現(xiàn)實(shí)意義的整體(對象)。
3 對認(rèn)定的主題的測試
主題是在對象和結(jié)構(gòu)的基礎(chǔ)上更高一層的抽象,是為了提供OOA分析結(jié)果的可見性,如同文章對各部分內(nèi)容的概要。對主題層的測試應(yīng)該考慮以下方面:
3.1 貫徹George Miller 的"7+2"原則(參見[3]),如果主題個數(shù)超過7個,就要求對有較密切屬性和服務(wù)的主題進(jìn)行歸并。
3.2 主題所反映的一組對象和結(jié)構(gòu)是否具有相同和相近的屬性和服務(wù)。
3.3 認(rèn)定的主題是否是對象和結(jié)構(gòu)更高層的抽象,是否便于理解OOA結(jié)果的概貌(尤其是對非技術(shù)人員的OOA 結(jié)果讀者)。
3.4 主題間的消息聯(lián)系(抽象)是否代表了主題所反映的對象和結(jié)構(gòu)之間的所有關(guān)聯(lián)。
4 對定義的屬性和實(shí)例關(guān)聯(lián)的測試
屬性是用來描述對象或結(jié)構(gòu)所反映的實(shí)例的特性。而實(shí)例關(guān)聯(lián)是反映實(shí)例集合間的映射關(guān)系。對屬性和實(shí)例關(guān)聯(lián)的測試從如下方面考慮:
4.1 定義的屬性是否對相應(yīng)的對象和分類結(jié)構(gòu)的每個現(xiàn)實(shí)實(shí)例都適用。
4.2 定義的屬性在現(xiàn)實(shí)世界是否與這種實(shí)例關(guān)系密切。
4.3 定義的屬性在問題空間是否與這種實(shí)例關(guān)系密切。
4.4 定義的屬性是否能夠不依賴于其他屬性被獨(dú)立理解。
4.5 定義的屬性在分類結(jié)構(gòu)中的位置是否恰當(dāng),低層對象的共有屬性是否在上層對象屬性體現(xiàn)。
4.6 在問題空間中每個對象的屬性是否定義完整。
4.7 定義的實(shí)例關(guān)聯(lián)是否符合現(xiàn)實(shí)。
4.8 在問題空間中實(shí)例關(guān)聯(lián)是否定義完整,特別需要注意1-多和多-多的實(shí)例關(guān)聯(lián)。
5 對定義的服務(wù)和消息關(guān)聯(lián)的測試
定義的服務(wù),就是定義的每一種對象和結(jié)構(gòu)在問題空間所要求的行為。由于問題空中實(shí)例間必要的通信,在OOA 中相應(yīng)需要定義消息關(guān)聯(lián)(詳細(xì)內(nèi)容參見[3])。對定義的服務(wù)和消息關(guān)聯(lián)的測試從如下方面進(jìn)行:
5.1 對象和結(jié)構(gòu)在問題空間的不同狀態(tài)是否定義了相應(yīng)的服務(wù)。
5.2 對象或結(jié)構(gòu)所需要的服務(wù)是否都定義了相應(yīng)的消息關(guān)聯(lián)。
5.3 定義的消息關(guān)聯(lián)所指引的服務(wù)提供是否正確。
5.4 沿著消息關(guān)聯(lián)執(zhí)行的線程是否合理,是否符合現(xiàn)實(shí)過程。
5.5 定義的服務(wù)是否重復(fù),是否定義了能夠得到的服務(wù)。
六面向?qū)ο笤O(shè)計(jì)的測試(OOD Test)
通常的結(jié)構(gòu)化的設(shè)計(jì)方法,用的"是面向作業(yè)的設(shè)計(jì)方法,它把系統(tǒng)分解以后,提出一組作業(yè),這些作業(yè)是以過程實(shí)現(xiàn)系統(tǒng)的基礎(chǔ)構(gòu)造,把問題域的分析轉(zhuǎn)化為求解域的設(shè)計(jì),分析的結(jié)果是設(shè)計(jì)階段的輸入"(參見[1])。
而面向?qū)ο笤O(shè)計(jì)(OOD)采用"造型的觀點(diǎn)",以O(shè)OA為基礎(chǔ)歸納出類,并建立類結(jié)構(gòu)或進(jìn)一步構(gòu)造成類庫,實(shí)現(xiàn)分析結(jié)果對問題空間的抽象。OOD 歸納的類,可以是對象簡單的延續(xù),可以是不同對象的相同或相似的服務(wù)。由此可見,OOD不是在OOA上的另一思維方式的大動干戈,而是OOA的進(jìn)一步細(xì)化和更高層的抽象。所以,OOD與OOA 的界限通常是難以嚴(yán)格區(qū)分的。OOD確定類和類結(jié)構(gòu)不僅是滿足當(dāng)前需求分析的要求,更重要的是通過重新組合或加以適當(dāng)?shù)难a(bǔ)充,能方便實(shí)現(xiàn)功能的重用和擴(kuò)增,以不斷適應(yīng)用戶的要求。因此,對OOD的測試,本文建議針對功能的實(shí)現(xiàn)和重用以及對OOA結(jié)果的拓展,從如下三方面考慮:
☆ 對認(rèn)定的類的測試
☆ 對構(gòu)造的類層次結(jié)構(gòu)的測試
☆ 對類庫的支持的測試
1 對認(rèn)定的類的測試
OOD認(rèn)定的類可以是OOA中認(rèn)定的對象,也可以是對象所需要的服務(wù)的抽象,對象所具有的屬性的抽象。認(rèn)定的類原則上應(yīng)該盡量基礎(chǔ)性,這樣才便于維護(hù)和重用。參考[4][5]中所提出的一些準(zhǔn)則,測試認(rèn)定的類:
1.1 是否含蓋了OOA中所有認(rèn)定的對象。
1.2 是否能體現(xiàn)OOA中定義的屬性。
1.3 是否能實(shí)現(xiàn)OOA中定義的服務(wù)。
1.4 是否對應(yīng)著一個含義明確的數(shù)據(jù)抽象。
1.5 是否盡可能少的依賴其他類。
1.6 類中的方法(C++:類的成員函數(shù))是否單用途。
2 對構(gòu)造的類層次結(jié)構(gòu)的測試
為能充分發(fā)揮面向?qū)ο蟮睦^承共享特性,OOD的類層次結(jié)構(gòu),通?;贠OA中產(chǎn)生的分類結(jié)構(gòu)的原則來組織,著重體現(xiàn)父類和子類間一般性和特殊性。兩者概念上的差異,請參見[1]。在當(dāng)前的問題空間,對類層次結(jié)構(gòu)的主要要求是能在解空間構(gòu)造實(shí)現(xiàn)全部功能的結(jié)構(gòu)框架。為此,測試如下方面:
2.1 類層次結(jié)構(gòu)是否含蓋了所有定義的類。
2.2 是否能體現(xiàn)OOA中所定義的實(shí)例關(guān)聯(lián)。
2.3 是否能實(shí)現(xiàn)OOA中所定義的消息關(guān)聯(lián)。
2.4 子類是否具有父類沒有的新特性。
2.5 子類間的共同特性是否完全在父類中得以體現(xiàn)。
3 對類庫支持的測試
對類庫的支持雖然也屬于類層次結(jié)構(gòu)的組織問題,但其強(qiáng)調(diào)的重點(diǎn)是再次軟件開發(fā)的重用。由于它并不直接影響當(dāng)前軟件的開發(fā)和功能實(shí)現(xiàn),因此,將其單獨(dú)提出來測試,也可作為對高質(zhì)量類層次結(jié)構(gòu)的評估。參照[9]中提出的準(zhǔn)則,擬訂測試點(diǎn)如下:
3.1 一組子類中關(guān)于某種含義相同或基本相同的操作,是否有相同的接口(包括名字和參數(shù)表)。
3.2 類中方法(C++:類的成員函數(shù))功能是否較單純,相應(yīng)的代碼行是否較少([5]中建議為不超過30行)。
3.3 類的層次結(jié)構(gòu)是否是深度大,寬度小。
七面向?qū)ο缶幊痰臏y試(OOP Test)
典型的面向?qū)ο蟪绦蚓哂欣^承、封裝和多態(tài)的新特性,這使得傳統(tǒng)的測試策略必須有所改變。封裝是對數(shù)據(jù)的隱藏,外界只能通過被提供的操作來訪問或修改數(shù)據(jù),這樣降低了數(shù)據(jù)被任意修改和讀寫的可能性,降低了傳統(tǒng)程序中對數(shù)據(jù)非法操作的測試。繼承是面向?qū)ο蟪绦虻闹匾攸c(diǎn),繼承使得代碼的重用率提高,同時也使錯誤傳播的概率提高。繼承使得傳統(tǒng)測試遇見了這樣一個難題:對繼承的代碼究竟應(yīng)該怎樣測試?(參見面向?qū)ο髥卧獪y試)。多態(tài)使得面向?qū)ο蟪绦驅(qū)ν獬尸F(xiàn)出強(qiáng)大的處理能力,但同時卻使得程序內(nèi)"同一"函數(shù)的行為復(fù)雜化,測試時不得不考慮不同類型具體執(zhí)行的代碼和產(chǎn)生的行為。
面向?qū)ο蟪绦蚴前压δ艿膶?shí)現(xiàn)分布在類中。能正確實(shí)現(xiàn)功能的類,通過消息傳遞來協(xié)同實(shí)現(xiàn)設(shè)計(jì)要求的功能。正是這種面向?qū)ο蟪绦蝻L(fēng)格,將出現(xiàn)的錯誤能精確的確定在某一具體的類。因此,在面向?qū)ο缶幊蹋∣OP)階段,忽略類功能實(shí)現(xiàn)的細(xì)則,將測試的目光集中在類功能的實(shí)現(xiàn)和相應(yīng)的面向?qū)ο蟪绦蝻L(fēng)格,主要體現(xiàn)為以下兩個方面(假設(shè)編程使用C++語言)。
☆ 數(shù)據(jù)成員是否滿足數(shù)據(jù)封裝的要求
☆ 類是否實(shí)現(xiàn)了要求的功能
1 數(shù)據(jù)成員是否滿足數(shù)據(jù)封裝的要求
數(shù)據(jù)封裝是數(shù)據(jù)和數(shù)據(jù)有關(guān)的操作的集合。檢查數(shù)據(jù)成員是否滿足數(shù)據(jù)封裝的要求,基本原則是數(shù)據(jù)成員是否被外界(數(shù)據(jù)成員所屬的類或子類以外的調(diào)用)直接調(diào)用。更直觀的說,當(dāng)改編數(shù)據(jù)成員的結(jié)構(gòu)時,是否影響了類的對外接口,是否會導(dǎo)致相應(yīng)外界必須改動。值得注意,有時強(qiáng)制的類型轉(zhuǎn)換會破壞數(shù)據(jù)的封裝特性。例如:
class Hiden
{private:
int a=1;
char *p= "hiden";}
class Visible
{public:
int b=2;
char *s= "visible";}
…..
…..
Hiden pp;
Visible *qq=(Visible *)&pp;
在上面的程序段中,pp的數(shù)據(jù)成員可以通過qq被隨意訪問。
2 類是否實(shí)現(xiàn)了要求的功能
類所實(shí)現(xiàn)的功能,都是通過類的成員函數(shù)執(zhí)行。在測試類的功能實(shí)現(xiàn)時,應(yīng)該首先保證類成員函數(shù)的正確性。單獨(dú)的看待類的成員函數(shù),與面向過程程序中的函數(shù)或過程沒有本質(zhì)的區(qū)別,幾乎所有傳統(tǒng)的單元測試中所使用的方法,都可在面向?qū)ο蟮膯卧獪y試中使用。具體的測試方法在面向?qū)ο蟮膯卧獪y試中介紹。類函數(shù)成員的正確行為只是類能夠?qū)崿F(xiàn)要求的功能的基礎(chǔ),類成員函數(shù)間的作用和類之間的服務(wù)調(diào)用是單元測試無法確定的。因此,需要進(jìn)行面向?qū)ο蟮募蓽y試。具體的測試方法在面向?qū)ο蟮募蓽y試中介紹。需要著重聲明,測試類的功能,不能僅滿足于代碼能無錯運(yùn)行或被測試類能提供的功能無錯,應(yīng)該以所做的OOD結(jié)果為依據(jù),檢測類提供的功能是否滿足設(shè)計(jì)的要求,是否有缺陷。必要時(如通過OOD結(jié)仍不清楚明確的地方)還應(yīng)該參照OOA的結(jié)果,以之為最終標(biāo)準(zhǔn)。
八面向?qū)ο蟮膯卧獪y試(OO Unit Test)
傳統(tǒng)的單元測試是針對程序的函數(shù)、過程或完成某一定功能的程序塊。沿用單元測試的概念,實(shí)際測試類成員函數(shù)。一些傳統(tǒng)的測試方法在面向?qū)ο蟮膯卧獪y試中都可以使用。如等價類劃分法,因果圖法,邊值分析法,邏輯覆蓋法,路徑分析法,程序插裝法等等,方法的具體實(shí)現(xiàn)參見[6]。單元測試一般建議由程序員完成。
用于單元級測試進(jìn)行的測試分析(提出相應(yīng)的測試要求)和測試用例(選擇適當(dāng)?shù)妮斎耄_(dá)到測試要求),規(guī)模和難度等均遠(yuǎn)小于后面將介紹的對整個系統(tǒng)的測試分析和測試用例,而且強(qiáng)調(diào)對語句應(yīng)該有100%的執(zhí)行代碼覆蓋率。在設(shè)計(jì)測試用例選擇輸入數(shù)據(jù)時,可以基于以下兩個假設(shè):
1. 如果函數(shù)(程序)對某一類輸入中的一個數(shù)據(jù)正確執(zhí)行,對同類中的其他輸入也能正確執(zhí)行。該假設(shè)的思想可參見[6]中介紹的等價類劃分。
2. 如果函數(shù)(程序)對某一復(fù)雜度的輸入正確執(zhí)行,對更高復(fù)雜度的輸入也能正確執(zhí)行。例如需要選擇字符串作為輸入時,基于本假設(shè),就無須計(jì)較于字符串的長度。除非字符串的長度是要求固定的,如IP地址字符串。
在面向?qū)ο蟪绦蛑?,類成員函數(shù)通常都很小,功能單一,函數(shù)的間調(diào)用頻繁,容易出現(xiàn)一些不宜發(fā)現(xiàn)的錯誤。例如:
· if (-1==write (fid, buffer, amount)) error_out();
該語句沒有全面檢查write()的返回值,無意中斷然假設(shè)了只有數(shù)據(jù)被完全寫入和沒有寫入兩種情況。當(dāng)測試也忽略了數(shù)據(jù)部分寫入的情況,就給程序遺留了隱患。
· 按程序的設(shè)計(jì),使用函數(shù)strrchr()查找最后的匹配字符,但誤程序中寫成了函數(shù)strchr(),使程序功能實(shí)現(xiàn)時查找的是第一個匹配字符。
· 程序中將if (strncmp(str1,str2,strlen(str1)))誤寫成了
if (strncmp(str1,str2,strlen(str2)))。如果測試用例中使用的數(shù)據(jù)str1和str2長度一樣,就無法檢測出。
因此,在做測試分析和設(shè)計(jì)測試用例時,應(yīng)該注意面向?qū)ο蟪绦虻倪@個特點(diǎn),仔細(xì)的進(jìn)行測試分析和設(shè)計(jì)測試用例,尤其是針對以函數(shù)返回值作為條件判斷選擇,字符串操作等情況。
面向?qū)ο缶幊痰奶匦允沟脤Τ蓡T函數(shù)的測試,又不完全等同于傳統(tǒng)的函數(shù)或過程測試。尤其是繼承特性和多態(tài)特性,使子類繼承或過載的父類成員函數(shù)出現(xiàn)了傳統(tǒng)測試中未遇見的問題。在[7]中,Brian Marick 給出了二方面的考慮:
1. 繼承的成員函數(shù)是否都不需要測試?
根據(jù)[7]中的論述,對父類中已經(jīng)測試過的成員函數(shù),兩種情況需要在子類中重新測試:a)繼承的成員函數(shù)在子類中做了改動;b)成員函數(shù)調(diào)用了改動過的成員函數(shù)的部分。例如:
假設(shè)父類Bass有兩個成員函數(shù):Inherited()和Redefined(),子類Derived只對Redefined()做了改動?! erived::Redefined()顯然需要重新測試。對于Derived::Inherited(),如果它有調(diào)用Redefined()的語句(如:x=x/Redefined()),就需要重新測試,反之,無此必要。
2. 對父類的測試是否能照搬到子類?
援用上面的假設(shè),Base::Redefined()和Derived::Redefined()已經(jīng)是不同的成員函數(shù),它們有不同的服務(wù)說明和執(zhí)行。對此,照理應(yīng)該對 Derived::Redefined()重新測試分析,設(shè)計(jì)測試用例。但由于面向?qū)ο蟮睦^承使得兩個函數(shù)有相似,故只需在 Base::Redefined()的測試要求和測試用例上添加對Derived::Redfined()新的測試要求和增補(bǔ)相應(yīng)的測試用例。例如:
Base::Redefined()含有如下語句
If (value<0) message ("less");
else if (value==0) message ("equal");
else message ("more");
Derived::Redfined()中定義為
If (value<0) message ("less");
else if (value==0) message ("It is equal");
else
{message ("more");
if (value==88)message("luck");}
在原有的測試上,對Derived::Redfined()的測試只需做如下改動:將value==0的測試結(jié)果期望改動;增加value==88的測試。
多態(tài)有幾種不同的形式,如參數(shù)多態(tài),包含多態(tài),過載多態(tài)。包含多態(tài)和過載多態(tài)在面向?qū)ο笳Z言中通常體現(xiàn)在子類與父類的繼承關(guān)系,對這兩種多態(tài)的測試參見上述對父類成員函數(shù)繼承和過載的論述。包含多態(tài)雖然使成員函數(shù)的參數(shù)可有多種類型,但通常只是增加了測試的繁雜。對具有包含多態(tài)的成員函數(shù)測試時,只需要在原有的測試分析和基礎(chǔ)上擴(kuò)大測試用例中輸入數(shù)據(jù)的類型的考慮。對類為粒度進(jìn)行面向?qū)ο蟮膯卧獪y試,可參考[10]中關(guān)于如何從MtSS生成測試用例的說明。
九面向?qū)ο蟮募蓽y試(OO Integrate Test)
傳統(tǒng)的集成測試,是由底向上通過集成完成的功能模塊進(jìn)行測試,一般可以在部分程序編譯完成的情況下進(jìn)行。而對于面向?qū)ο蟪绦?,相互調(diào)用的功能是散布在程序的不同類中,類通過消息相互作用申請和提供服務(wù)。類的行為與它的狀態(tài)密切相關(guān),狀態(tài)不僅僅是體現(xiàn)在類數(shù)據(jù)成員的值,也許還包括其他類中的狀態(tài)信息。由此可見,類相互依賴極其緊密,根本無法在編譯不完全的程序上對類進(jìn)行測試。所以,面向?qū)ο蟮募蓽y試通常需要在整個程序編譯完成后進(jìn)行。此外,面向?qū)ο蟪绦蚓哂袆討B(tài)特性,程序的控制流往往無法確定,因此也只能對整個編譯后的程序做基于黑盒子的集成測試。
面向?qū)ο蟮募蓽y試能夠檢測出相對獨(dú)立的單元測試無法檢測出的那些類相互作用時才會產(chǎn)生的錯誤?;趩卧獪y試對成員函數(shù)行為正確性的保證,集成測試只關(guān)注于系統(tǒng)的結(jié)構(gòu)和內(nèi)部的相互作用。面向?qū)ο蟮募蓽y試可以分成兩步進(jìn)行:先進(jìn)行靜態(tài)測試,再進(jìn)行動態(tài)測試。
靜態(tài)測試主要針對程序的結(jié)構(gòu)進(jìn)行,檢測程序結(jié)構(gòu)是否符合設(shè)計(jì)要求?,F(xiàn)在流行的一些測試軟件都能提供一種稱為"可逆性工程"的功能,即通過原程序得到類關(guān)系圖和函數(shù)功能調(diào)用關(guān)系圖,例如International Software Automation 公司的Panorama-2 for Windows95、Rational公司的Rose C++ Analyzer等,將"可逆性工程"得到的結(jié)果與OOD的結(jié)果相比較,檢測程序結(jié)構(gòu)和實(shí)現(xiàn)上是否有缺陷。換句話說,通過這種方法檢測OOP是否達(dá)到了設(shè)計(jì)要求。
動態(tài)測試設(shè)計(jì)測試用例時,通常需要上述的功能調(diào)用結(jié)構(gòu)圖、類關(guān)系圖或者實(shí)體關(guān)系圖為參考,確定不需要被重復(fù)測試的部分,從而優(yōu)化測試用例,減少測試工作量,使得進(jìn)行的測試能夠達(dá)到一定覆蓋標(biāo)準(zhǔn)。測試所要達(dá)到的覆蓋標(biāo)準(zhǔn)可以是:達(dá)到類所有的服務(wù)要求或服務(wù)提供的一定覆蓋率;依據(jù)類間傳遞的消息,達(dá)到對所有執(zhí)行線程的一定覆蓋率;達(dá)到類的所有狀態(tài)的一定覆蓋率等。同時也可以考慮使用現(xiàn)有的一些測試工具來得到程序代碼執(zhí)行的覆蓋率。
具體設(shè)計(jì)測試用例,可參考下列步驟:
1. 先選定檢測的類,參考OOD分析結(jié)果,仔細(xì)出類的狀態(tài)和相應(yīng)的行為,類或成員函數(shù)間傳遞的消息,輸入或輸出的界定等。
2. 確定覆蓋標(biāo)準(zhǔn)。
3. 利用結(jié)構(gòu)關(guān)系圖確定待測類的所有關(guān)聯(lián)。
4. 根據(jù)程序中類的對象構(gòu)造測試用例,確認(rèn)使用什么輸入激發(fā)類的狀態(tài)、使用類的服務(wù)和期望產(chǎn)生什么行為等。
值得注意,設(shè)計(jì)測試用例時,不但要設(shè)計(jì)確認(rèn)類功能滿足的輸入,還應(yīng)該有意識的設(shè)計(jì)一些被禁止的例子,確認(rèn)類是否有不合法的行為產(chǎn)生,如發(fā)送與類狀態(tài)不相適應(yīng)的消息,要求不相適應(yīng)的服務(wù)等。根據(jù)具體情況,動態(tài)的集成測試,有時也可以通過系統(tǒng)測試完成。
十面向?qū)ο蟮南到y(tǒng)測試(OO System Test)
通過單元測試和集成測試,僅能保證軟件開發(fā)的功能得以實(shí)現(xiàn)。但不能確認(rèn)在實(shí)際運(yùn)行時,它是否滿足用戶的需要,是否大量存在實(shí)際使用條件下會被誘發(fā)產(chǎn)生錯誤的隱患。為此,對完成開發(fā)的軟件必須經(jīng)過規(guī)范的系統(tǒng)測試。換個角度說,開發(fā)完成的軟件僅僅是實(shí)際投入使用系統(tǒng)的一個組成部分,需要測試它與系統(tǒng)其他部分配套運(yùn)行的表現(xiàn),以保證在系統(tǒng)各部分協(xié)調(diào)工作的環(huán)境下也能正常工作。在后面對ZXM10收發(fā)臺系統(tǒng)測試的敘述可以看到,其他的系統(tǒng)設(shè)備(如監(jiān)控臺,圖象臺,E1接入設(shè)備,攝像頭等)如何配合收發(fā)臺的系統(tǒng)測試。
系統(tǒng)測試應(yīng)該盡量搭建與用戶實(shí)際使用環(huán)境相同的測試平臺,應(yīng)該保證被測系統(tǒng)的完整性,對臨時沒有的系統(tǒng)設(shè)備部件,也應(yīng)有相應(yīng)的模擬手段。系統(tǒng)測試時,應(yīng)該參考OOA分析的結(jié)果,對應(yīng)描述的對象、屬性和各種服務(wù),檢測軟件是否能夠完全"再現(xiàn)"問題空間。系統(tǒng)測試不僅是檢測軟件的整體行為表現(xiàn),從另一個側(cè)面看,也是對軟件開發(fā)設(shè)計(jì)的再確認(rèn)。
這里說的系統(tǒng)測試是對測試步驟的抽象描述。它體現(xiàn)的具體測試內(nèi)容包括:
· 功能測試:測試是否滿足開發(fā)要求,是否能夠提供設(shè)計(jì)所描述的功能,是否用戶的需求都得到滿足。功能測試是系統(tǒng)測試最常用和必須的測試,通常還會以正式的軟件說明書為測試標(biāo)準(zhǔn)。
· 強(qiáng)度測試:測試系統(tǒng)的能力最高實(shí)際限度,即軟件在一些超負(fù)荷的情況,功能實(shí)現(xiàn)情況。如要求軟件某一行為的大量重復(fù)、輸入大量的數(shù)據(jù)或大數(shù)值數(shù)據(jù)、對數(shù)據(jù)庫大量復(fù)雜的查詢等。
· 性能測試:測試軟件的運(yùn)行性能。這種測試常常與強(qiáng)度測試結(jié)合進(jìn)行,需要事先對被測軟件提出性能指標(biāo),如傳輸連接的最長時限、傳輸?shù)腻e誤率、計(jì)算的精度、記錄的精度、響應(yīng)的時限和恢復(fù)時限等。
· 安全測試:驗(yàn)證安裝在系統(tǒng)內(nèi)的保護(hù)機(jī)構(gòu)確實(shí)能夠?qū)ο到y(tǒng)進(jìn)行保護(hù),使之不受各種非常的干擾。安全測試時需要設(shè)計(jì)一些測試用例試圖突破系統(tǒng)的安全保密措施,檢驗(yàn)系統(tǒng)是否有安全保密的漏洞。
· 恢復(fù)測試:采用人工的干擾使軟件出錯,中斷使用,檢測系統(tǒng)的恢復(fù)能力,特別是通訊系統(tǒng)?;謴?fù)測試時,應(yīng)該參考性能測試的相關(guān)測試指標(biāo)。
· 可用性測試:測試用戶是否能夠滿意使用。具體體現(xiàn)為操作是否方便,用戶界面是否友好等。
· 安裝/卸載測試(install/uninstall test)等等。
系統(tǒng)測試需要對被測的軟件結(jié)合需求分析做仔細(xì)的測試分析,建立測試用例。
十一參考文獻(xiàn)(Reference)
[1] 蔡希堯陳平,面向?qū)ο蠹夹g(shù),西安電子科技大學(xué)出版社,1993年11 月
[2] Coad, P. And Yourdon, E. , "Object-Oriented Analysis", Yourdon Press, 1989
[3] 湯庸,軟件工程方法學(xué)及應(yīng)用,中國三峽出版社,1998年1月
[4] Winblad, A.L. , Edwares, S.D., and King, D.R. , "Object-Oriented Software", Addison-Wesley, 1990
[5] Johnson, R.E. and Foote, B., "Designing Reusable Classes, Journal of Object-Oriented Programming", Vol.1, No.2, 1988
[6] 鄭人杰,計(jì)算機(jī)軟件測試技術(shù),清華大學(xué)出版社,1992年12月
[7] Brian Marick, "Notes on Object-Oriented Testing",
http://www.stlabs.com/marick
[8] Prof. Alfred Strohmeier, Dr. Didier Buchs,M. Karol Frühauf, Dr. Pascale Thévenod-Fosse, and Prof. Alain Wegmann, "Test Selection for Specification-Based Unit Testing of Object-Oriented Software based on Formal Specifications",http://lglwww.epfl.ch/~barbey/PhD/
[9] Robert V. Binder,"The FREE Approach to Testing Object-Oriented Software: An Overview.",http://www.rbsc.com/pages/FREE.html