一 摘要(Abstract)
[摘要]
面向對象技術(shù)在軟件工程中的推廣使用,使得傳統的測試技術(shù)和方法受到了極大的沖擊。對面向對象技術(shù)所引入的新特點(diǎn),傳統的測試技術(shù)已經(jīng)無(wú)法有效的進(jìn)行測試。對面向對象軟件的測試,測試策略或方法都需要出現相應的變革或更新。
就此,本文結合傳統的測試技術(shù),針對面向對象技術(shù)新特性在測試中所引發(fā)的問(wèn)題,提出一種測試模型。首先,以軟件工程中面向對象軟件開(kāi)發(fā)模式為參考,分別在面向對象分析,面向對象設計,面向對象編程三個(gè)階段,依據各階段的地位,作用,實(shí)現目標,具體闡述測試目的和應該注意的測試點(diǎn)。其次,依照傳統的三個(gè)測試步驟:?jiǎn)卧獪y試,集成測試,系統測試,借鑒傳統測試方法有用的部分,論述如何有效的對面向對象軟件進(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) 面向對象(OO: Object-Oriented)
三 引言(Introduction)
用戶(hù)使用低質(zhì)量的軟件,在運行過(guò)程中會(huì )產(chǎn)生各種各樣的問(wèn)題,可能帶來(lái)不同程度的嚴重后果,輕者影響系統的正常工作,重者造成事故,損失生命財產(chǎn)。軟件測試是保證軟件質(zhì)量的最重要的手段。什么是軟件測試?1983年IEEE定義為:使用人工或自動(dòng)手段來(lái)運行或測定某個(gè)系統的過(guò)程,其目的在于檢驗它是否滿(mǎn)足規定的需求或是弄清預期結果與實(shí)際結果之間的差別。
現代的軟件開(kāi)發(fā)工程是將整個(gè)軟件開(kāi)發(fā)過(guò)程明確的劃分為幾個(gè)階段(參見(jiàn)[6]的論述),將復雜問(wèn)題具體按階段加以解決。這樣,在軟件的整個(gè)開(kāi)發(fā)過(guò)程中,可以對每一階段提出若干明確的監控點(diǎn),作為各階段目標實(shí)現的檢驗標準,從而提高開(kāi)發(fā)過(guò)程的可見(jiàn)度和保證開(kāi)發(fā)過(guò)程的正確性。經(jīng)驗證明,軟件的質(zhì)量不僅是體現在程序的正確性上,它和編碼以前所做的需求分析,軟件設計密切相關(guān)。軟件使用中出現的錯誤,不一定是編程人員在編碼階段引入的,很可能在程序設計,甚而需求分析時(shí)就埋下了禍因。這時(shí),對錯誤的糾正往往不能通過(guò)可能會(huì )誘發(fā)更多錯誤的簡(jiǎn)單的修修補補,而必須追溯到軟件開(kāi)發(fā)的最初階段。這無(wú)疑增大了軟件的開(kāi)發(fā)費用。因此,為了保證軟件的質(zhì)量,我們應該著(zhù)眼于整個(gè)軟件生存期,特別是著(zhù)眼于編碼以前的各開(kāi)發(fā)階段的工作。這樣,軟件測試的概念和實(shí)施范圍必須擴充,應該包括在整個(gè)開(kāi)發(fā)各階段的復查、評估和檢測。由此,廣義的軟件測試實(shí)際是由確認、驗證、測試三個(gè)方面組成(注:本文對后面用廣義測試概念處不另加標識):
確認:是評估將要開(kāi)發(fā)的軟件產(chǎn)品是否是正確無(wú)誤、可行和有價(jià)值的。比如,將要開(kāi)發(fā)的軟件是否會(huì )滿(mǎn)足用戶(hù)提出的要求,是否能在將來(lái)的實(shí)際使用環(huán)境中正確穩定的運行,是否存在隱患等。這里包含了對用戶(hù)需求滿(mǎn)足程度的評價(jià)。確認意味著(zhù)確保一個(gè)待開(kāi)發(fā)軟件是正確無(wú)誤的,是對軟件開(kāi)發(fā)構想的檢測。
驗證:是檢測軟件開(kāi)發(fā)的每個(gè)階段、每個(gè)步驟的結果是否正確無(wú)誤,是否與軟件開(kāi)發(fā)各階段的要求或期望的結果相一致。驗證意味著(zhù)確保軟件是會(huì )正確無(wú)誤的實(shí)現軟件的需求,開(kāi)發(fā)過(guò)程是沿著(zhù)正確的方向在進(jìn)行。
測試:與狹隘的測試概念統一。通常是經(jīng)過(guò)單元測試、集成測試、系統測試三個(gè)環(huán)節。
在整個(gè)軟件生存期(參見(jiàn)[6]中的劃分),確認、驗證、測試分別有其側重的階段。確認主要體現在計劃階段、需求分析階段、也會(huì )出現在測試階段;驗證主要體現在設計階段和編碼階段;測試主要體現在編碼階段和測試階段。事實(shí)上,確認、驗證、測試是相輔相成的。確認無(wú)疑會(huì )產(chǎn)生驗證和測試的標準,而驗證和測試通常又會(huì )幫助完成一些確認,特別是在系統測試階段。
面向對象技術(shù)是一種全新的軟件開(kāi)發(fā)技術(shù),正逐漸代替被廣泛使用的面向過(guò)程開(kāi)發(fā)方法,被看成是解決軟件危機的新興技術(shù)。面向對象技術(shù)產(chǎn)生更好的系統結構,更規范的編程風(fēng)格,極大的優(yōu)化了數據使用的安全性,提高了程序代碼的重用,一些人就此認為面向對象技術(shù)開(kāi)發(fā)出的程序無(wú)需進(jìn)行測試。應該看到,盡管面向對象技術(shù)的基本思想保證了軟件應該有更高的質(zhì)量,但實(shí)際情況卻并非如此,因為無(wú)論采用什么樣的編程技術(shù),編程人員的錯誤都是不可避免的,而且由于面向對象技術(shù)開(kāi)發(fā)的軟件代碼重用率高,更需要嚴格測試,避免錯誤的繁衍。因此,軟件測試并沒(méi)有面向對象編程的興起而喪失掉它的重要性。
從1982年在美國北卡羅來(lái)納大學(xué)召開(kāi)首次軟件測試的正式技術(shù)會(huì )議至今,軟件測試理論迅速發(fā)展,并相應出現了各種軟件測試方法,使軟件測試技術(shù)得到極大的提高。然而,一度實(shí)踐證明行之有效的軟件測試對面向對象技術(shù)開(kāi)發(fā)的軟件多少顯得有些力不從心。尤其是面向對象技術(shù)所獨有的多態(tài),繼承,封裝等新特點(diǎn),產(chǎn)生了傳統語(yǔ)言設計所不存在的錯誤可能性,或者使得傳統軟件測試中的重點(diǎn)不再顯得突出,或者使原來(lái)測試經(jīng)驗認為和實(shí)踐證明的次要方面成為了主要問(wèn)題。例如:
在傳統的面向過(guò)程程序中,對于函數
y=Function(x);
你只需要考慮一個(gè)函數(Function())的行為特點(diǎn),而在面向對象程序中,你不得不同時(shí)考慮基類(lèi)函數(Base::Function())的行為和繼承類(lèi)函數(Derived::Function())的行為。
面向對象程序的結構不再是傳統的功能模塊結構,作為一個(gè)整體,原有集成測試所要求的逐步將開(kāi)發(fā)的模塊搭建在一起進(jìn)行測試的方法已成為不可能。而且,面向對象軟件拋棄了傳統的開(kāi)發(fā)模式,對每個(gè)開(kāi)發(fā)階段都有不同以往的要求和結果,已經(jīng)不可能用功能細化的觀(guān)點(diǎn)來(lái)檢測面向對象分析和設計的結果。因此,傳統的測試模型對面向對象軟件已經(jīng)不再適用。針對面向對象軟件的開(kāi)發(fā)特點(diǎn),應該有一種新的測試模型。
四 面向對象測試模型(Object-Orient Test Model)
面向對象的開(kāi)發(fā)模型突破了傳統的瀑布模型,將開(kāi)發(fā)分為面向對象分析(OOA),面向對象設計(OOD),和面向對象編程(OOP)三個(gè)階段。分析階段產(chǎn)生整個(gè)問(wèn)題空間的抽象描述,在此基礎上,進(jìn)一步歸納出適用于面向對象編程語(yǔ)言的類(lèi)和類(lèi)結構,最后形成代碼。由于面向對象的特點(diǎn),采用這種開(kāi)發(fā)模型能有效的將分析設計的文本或圖表代碼化,不斷適應用戶(hù)需求的變動(dòng)。針對這種開(kāi)發(fā)模型,結合傳統的測試步驟的劃分,本文建議一種整個(gè)軟件開(kāi)發(fā)過(guò)程中不斷測試的測試模型,使開(kāi)發(fā)階段的測試與編碼完成后的單元測試、集成測試、系統測試成為一個(gè)整體。測試模型如下圖所示:
0 面向對象編程
OOA Test:面向對象分析的測試 OOD Test:面向對象設計的測試
OOP Test:面向對象編程的測試 OO Unit Test:面向對象單元測試
OO Integrate Test:面向對象集成測試 OO System Test:面向對象系統測試
OOA Test和OOD Test 是對分析結果和設計結果的測試,主要是對分析設計產(chǎn)生的文本進(jìn)行,是軟件開(kāi)發(fā)前期的關(guān)鍵性測試。OOP Test主要針對編程風(fēng)格和程序代碼實(shí)現進(jìn)行測試,其主要的測試內容在面向對象單元測試和面向對象集成測試中體現。面向對象單元測試是對程序內部具體單一的功能模塊的測試,如果程序是用C++語(yǔ)言實(shí)現,主要就是對類(lèi)成員函數的測試。面向對象單元測試是進(jìn)行面向對象集成測試的基礎。面向對象集成測試主要對系統內部的相互服務(wù)進(jìn)行測試,如成員函數間的相互作用,類(lèi)間的消息傳遞等。面向對象集成測試不但要基于面向對象單元測試,更要參見(jiàn)OOD或OOD Test結果(詳見(jiàn)后敘述)。面向對象系統測試是基于面向對象集成測試的最后階段的測試,主要以用戶(hù)需求為測試標準,需要借鑒OOA或OOA Test結果。
盡管上述各階段的測試構成一相互作用的整體,但其測試的主體、方向和方法各有不同,且為敘述的方便,本文接下來(lái)將從OOA,OOD,OOP,單元測試,集成測試,系統測試六個(gè)方面分別介紹對面向對象軟件的測試。
對由OOA,OOP,OOD這三個(gè)開(kāi)發(fā)階段所構成的開(kāi)發(fā)模型、各階段應該完成的目標以及結果報告的形式等詳細介紹,已經(jīng)超出本文內容,請參見(jiàn)[1]。
五 面向對象分析的測試(OOA Test)
傳統的面向過(guò)程分析是一個(gè)功能分解的過(guò)程,是把一個(gè)系統看成可以分解的功能的集合。這種傳統的功能分解分析法的著(zhù)眼點(diǎn)在于一個(gè)系統需要什么樣的信息處理方法和過(guò)程,以過(guò)程的抽象來(lái)對待系統的需要。而面向對象分析(OOA)是"把E-R圖和語(yǔ)義網(wǎng)絡(luò )模型,即信息造型中的概念,與面向對象程序設計語(yǔ)言中的重要概念結合在一起而形成的分析方法"(參見(jiàn)[1]),最后通常是得到問(wèn)題空間的圖表的形式描述。
OOA直接映射問(wèn)題空間,全面的將問(wèn)題空間中實(shí)現功能的現實(shí)抽象化。將問(wèn)題空間中的實(shí)例抽象為對象(不同于C++中的對象概念),用對象的結構反映問(wèn)題空間的復雜實(shí)例和復雜關(guān)系,用屬性和服務(wù)表示實(shí)例的特性和行為。對一個(gè)系統而言,與傳統分析方法產(chǎn)生的結果相反,行為是相對穩定的,結構是相對不穩定的,這更充分反映了現實(shí)的特性。OOA的結果是為后面階段類(lèi)的選定和實(shí)現,類(lèi)層次結構的組織和實(shí)現提供平臺。因此,OOA對問(wèn)題空間分析抽象的不完整,最終會(huì )影響軟件的功能實(shí)現,導致軟件開(kāi)發(fā)后期大量可避免的修補工作;而一些冗余的對象或結構會(huì )影響類(lèi)的選定、程序的整體結構或增加程序員不必要的工作量。因此,本文對OOA的測試重點(diǎn)在其完整性和冗余性。
盡管OOA的測試是一個(gè)不可分割的系統過(guò)程,為敘述的方便,鑒于[2]中Coad方法所提出的OOA實(shí)現步驟,對OOA階段的測試劃分為以下五個(gè)方面:
☆ 對認定的對象的測試
☆ 對認定的結構的測試
☆ 對認定的主題的測試
☆ 對定義的屬性和實(shí)例關(guān)聯(lián)的測試
☆ 對定義的服務(wù)和消息關(guān)聯(lián)的測試
對象、結構、主題等在OOA結果中的位置,參見(jiàn)下圖:
1 對認定的對象的測試:
OOA中認定的對象是對問(wèn)題空間中的結構,其他系統,設備,被記憶的事件,系統涉及的人員等實(shí)際實(shí)例的抽象(參見(jiàn)[2])。對它的測試可以從如下方面考慮:
1.1 認定的對象是否全面,是否問(wèn)題空間中所有涉及到的實(shí)例都反映在認定的抽象對象中。
1.2 認定的對象是否具有多個(gè)屬性。只有一個(gè)屬性的對象通常應看成其他對象的屬性,而不是抽象為獨立的對象。
1.3 對認定為同一對象的實(shí)例是否有共同的,區別于其他實(shí)例的共同屬性。
1.4 對認定為同一對象的實(shí)例是否提供或需要相同的服務(wù),如果服務(wù)隨著(zhù)不同的實(shí)例而變化,認定的對象就需要分解或利用繼承性來(lái)分類(lèi)表示。
1.5 如果系統沒(méi)有必要始終保持對象代表的實(shí)例的信息,提供或者得到關(guān)于它的服務(wù),認定的對象也無(wú)必要。
1.6 認定的對象的名稱(chēng)應該盡量準確,適用。
2 對認定的結構的測試
在Coad方法中,認定的結構指的是多種對象的組織方式,用來(lái)反映問(wèn)題空間中的復雜實(shí)例和復雜關(guān)系。認定的結構分為兩種:分類(lèi)結構和組裝結構。分類(lèi)結構體現了問(wèn)題空間中實(shí)例的一般與特殊的關(guān)系,組裝結構體現了問(wèn)題空間中實(shí)例整體與局部的關(guān)系。
2.1 對認定的分類(lèi)結構的測試可從如下方面著(zhù)手:
2.1.1 對于結構中的一種對象,尤其是處于高層的對象,是否在問(wèn)題空間中含有不同于下一層對象的特殊可能性,即是否能派生出下一層對象。
2.1.2 對于結構中的一種對象,尤其是處于同一低層的對象,是否能抽象出在現實(shí)中有意義的更一般的上層對象。
2.1.3 對所有認定的對象,是否能在問(wèn)題空間內向上層抽象出在現實(shí)中有意義的對象
2.1.4 高層的對象的特性是否完全體現下層的共性
2.1.5 低層的對象是否有高層特性基礎上的特殊性
2.2 對認定的組裝結構的測試從如下方面入手:
2.2.1 整體(對象)和部件(對象)的組裝關(guān)系是否符合現實(shí)的關(guān)系。
2.2.2 整體(對象)的部件(對象)是否在考慮的問(wèn)題空間中有實(shí)際應用。
2.2.3 整體(對象)中是否遺漏了反映在問(wèn)題空間中有用的部件(對象)。
2.2.4 部件(對象)是否能夠在問(wèn)題空間中組裝新的有現實(shí)意義的整體(對象)。
3 對認定的主題的測試
主題是在對象和結構的基礎上更高一層的抽象,是為了提供OOA分析結果的可見(jiàn)性,如同文章對各部分內容的概要。對主題層的測試應該考慮以下方面:
3.1 貫徹George Miller 的"7+2"原則(參見(jiàn)[3]),如果主題個(gè)數超過(guò)7個(gè),就要求對有較密切屬性和服務(wù)的主題進(jìn)行歸并。
3.2 主題所反映的一組對象和結構是否具有相同和相近的屬性和服務(wù)。
3.3 認定的主題是否是對象和結構更高層的抽象,是否便于理解OOA結果的概貌(尤其是對非技術(shù)人員的OOA 結果讀者)。
3.4 主題間的消息聯(lián)系(抽象)是否代表了主題所反映的對象和結構之間的所有關(guān)聯(lián)。
4 對定義的屬性和實(shí)例關(guān)聯(lián)的測試
屬性是用來(lái)描述對象或結構所反映的實(shí)例的特性。而實(shí)例關(guān)聯(lián)是反映實(shí)例集合間的映射關(guān)系。對屬性和實(shí)例關(guān)聯(lián)的測試從如下方面考慮:
4.1 定義的屬性是否對相應的對象和分類(lèi)結構的每個(gè)現實(shí)實(shí)例都適用。
4.2 定義的屬性在現實(shí)世界是否與這種實(shí)例關(guān)系密切。
4.3 定義的屬性在問(wèn)題空間是否與這種實(shí)例關(guān)系密切。
4.4 定義的屬性是否能夠不依賴(lài)于其他屬性被獨立理解。
4.5 定義的屬性在分類(lèi)結構中的位置是否恰當,低層對象的共有屬性是否在上層對象屬性體現。
4.6 在問(wèn)題空間中每個(gè)對象的屬性是否定義完整。
4.7 定義的實(shí)例關(guān)聯(lián)是否符合現實(shí)。
4.8 在問(wèn)題空間中實(shí)例關(guān)聯(lián)是否定義完整,特別需要注意1-多和多-多的實(shí)例關(guān)聯(lián)。
5 對定義的服務(wù)和消息關(guān)聯(lián)的測試
定義的服務(wù),就是定義的每一種對象和結構在問(wèn)題空間所要求的行為。由于問(wèn)題空中實(shí)例間必要的通信,在OOA 中相應需要定義消息關(guān)聯(lián)(詳細內容參見(jiàn)[3])。對定義的服務(wù)和消息關(guān)聯(lián)的測試從如下方面進(jìn)行:
5.1 對象和結構在問(wèn)題空間的不同狀態(tài)是否定義了相應的服務(wù)。
5.2 對象或結構所需要的服務(wù)是否都定義了相應的消息關(guān)聯(lián)。
5.3 定義的消息關(guān)聯(lián)所指引的服務(wù)提供是否正確。
5.4 沿著(zhù)消息關(guān)聯(lián)執行的線(xiàn)程是否合理,是否符合現實(shí)過(guò)程。
5.5 定義的服務(wù)是否重復,是否定義了能夠得到的服務(wù)。
六面向對象設計的測試(OOD Test)
通常的結構化的設計方法,用的"是面向作業(yè)的設計方法,它把系統分解以后,提出一組作業(yè),這些作業(yè)是以過(guò)程實(shí)現系統的基礎構造,把問(wèn)題域的分析轉化為求解域的設計,分析的結果是設計階段的輸入"(參見(jiàn)[1])。
而面向對象設計(OOD)采用"造型的觀(guān)點(diǎn)",以OOA為基礎歸納出類(lèi),并建立類(lèi)結構或進(jìn)一步構造成類(lèi)庫,實(shí)現分析結果對問(wèn)題空間的抽象。OOD 歸納的類(lèi),可以是對象簡(jiǎn)單的延續,可以是不同對象的相同或相似的服務(wù)。由此可見(jiàn),OOD不是在OOA上的另一思維方式的大動(dòng)干戈,而是OOA的進(jìn)一步細化和更高層的抽象。所以,OOD與OOA 的界限通常是難以嚴格區分的。OOD確定類(lèi)和類(lèi)結構不僅是滿(mǎn)足當前需求分析的要求,更重要的是通過(guò)重新組合或加以適當的補充,能方便實(shí)現功能的重用和擴增,以不斷適應用戶(hù)的要求。因此,對OOD的測試,本文建議針對功能的實(shí)現和重用以及對OOA結果的拓展,從如下三方面考慮:
☆ 對認定的類(lèi)的測試
☆ 對構造的類(lèi)層次結構的測試
☆ 對類(lèi)庫的支持的測試
1 對認定的類(lèi)的測試
OOD認定的類(lèi)可以是OOA中認定的對象,也可以是對象所需要的服務(wù)的抽象,對象所具有的屬性的抽象。認定的類(lèi)原則上應該盡量基礎性,這樣才便于維護和重用。參考[4][5]中所提出的一些準則,測試認定的類(lèi):
1.1 是否含蓋了OOA中所有認定的對象。
1.2 是否能體現OOA中定義的屬性。
1.3 是否能實(shí)現OOA中定義的服務(wù)。
1.4 是否對應著(zhù)一個(gè)含義明確的數據抽象。
1.5 是否盡可能少的依賴(lài)其他類(lèi)。
1.6 類(lèi)中的方法(C++:類(lèi)的成員函數)是否單用途。
2 對構造的類(lèi)層次結構的測試
為能充分發(fā)揮面向對象的繼承共享特性,OOD的類(lèi)層次結構,通?;贠OA中產(chǎn)生的分類(lèi)結構的原則來(lái)組織,著(zhù)重體現父類(lèi)和子類(lèi)間一般性和特殊性。兩者概念上的差異,請參見(jiàn)[1]。在當前的問(wèn)題空間,對類(lèi)層次結構的主要要求是能在解空間構造實(shí)現全部功能的結構框架。為此,測試如下方面:
2.1 類(lèi)層次結構是否含蓋了所有定義的類(lèi)。
2.2 是否能體現OOA中所定義的實(shí)例關(guān)聯(lián)。
2.3 是否能實(shí)現OOA中所定義的消息關(guān)聯(lián)。
2.4 子類(lèi)是否具有父類(lèi)沒(méi)有的新特性。
2.5 子類(lèi)間的共同特性是否完全在父類(lèi)中得以體現。
3 對類(lèi)庫支持的測試
對類(lèi)庫的支持雖然也屬于類(lèi)層次結構的組織問(wèn)題,但其強調的重點(diǎn)是再次軟件開(kāi)發(fā)的重用。由于它并不直接影響當前軟件的開(kāi)發(fā)和功能實(shí)現,因此,將其單獨提出來(lái)測試,也可作為對高質(zhì)量類(lèi)層次結構的評估。參照[9]中提出的準則,擬訂測試點(diǎn)如下:
3.1 一組子類(lèi)中關(guān)于某種含義相同或基本相同的操作,是否有相同的接口(包括名字和參數表)。
3.2 類(lèi)中方法(C++:類(lèi)的成員函數)功能是否較單純,相應的代碼行是否較少([5]中建議為不超過(guò)30行)。
3.3 類(lèi)的層次結構是否是深度大,寬度小。
七面向對象編程的測試(OOP Test)
典型的面向對象程序具有繼承、封裝和多態(tài)的新特性,這使得傳統的測試策略必須有所改變。封裝是對數據的隱藏,外界只能通過(guò)被提供的操作來(lái)訪(fǎng)問(wèn)或修改數據,這樣降低了數據被任意修改和讀寫(xiě)的可能性,降低了傳統程序中對數據非法操作的測試。繼承是面向對象程序的重要特點(diǎn),繼承使得代碼的重用率提高,同時(shí)也使錯誤傳播的概率提高。繼承使得傳統測試遇見(jiàn)了這樣一個(gè)難題:對繼承的代碼究竟應該怎樣測試?(參見(jiàn)面向對象單元測試)。多態(tài)使得面向對象程序對外呈現出強大的處理能力,但同時(shí)卻使得程序內"同一"函數的行為復雜化,測試時(shí)不得不考慮不同類(lèi)型具體執行的代碼和產(chǎn)生的行為。
面向對象程序是把功能的實(shí)現分布在類(lèi)中。能正確實(shí)現功能的類(lèi),通過(guò)消息傳遞來(lái)協(xié)同實(shí)現設計要求的功能。正是這種面向對象程序風(fēng)格,將出現的錯誤能精確的確定在某一具體的類(lèi)。因此,在面向對象編程(OOP)階段,忽略類(lèi)功能實(shí)現的細則,將測試的目光集中在類(lèi)功能的實(shí)現和相應的面向對象程序風(fēng)格,主要體現為以下兩個(gè)方面(假設編程使用C++語(yǔ)言)。
☆ 數據成員是否滿(mǎn)足數據封裝的要求
☆ 類(lèi)是否實(shí)現了要求的功能
1 數據成員是否滿(mǎn)足數據封裝的要求
數據封裝是數據和數據有關(guān)的操作的集合。檢查數據成員是否滿(mǎn)足數據封裝的要求,基本原則是數據成員是否被外界(數據成員所屬的類(lèi)或子類(lèi)以外的調用)直接調用。更直觀(guān)的說(shuō),當改編數據成員的結構時(shí),是否影響了類(lèi)的對外接口,是否會(huì )導致相應外界必須改動(dòng)。值得注意,有時(shí)強制的類(lèi)型轉換會(huì )破壞數據的封裝特性。例如:
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的數據成員可以通過(guò)qq被隨意訪(fǎng)問(wèn)。
2 類(lèi)是否實(shí)現了要求的功能
類(lèi)所實(shí)現的功能,都是通過(guò)類(lèi)的成員函數執行。在測試類(lèi)的功能實(shí)現時(shí),應該首先保證類(lèi)成員函數的正確性。單獨的看待類(lèi)的成員函數,與面向過(guò)程程序中的函數或過(guò)程沒(méi)有本質(zhì)的區別,幾乎所有傳統的單元測試中所使用的方法,都可在面向對象的單元測試中使用。具體的測試方法在面向對象的單元測試中介紹。類(lèi)函數成員的正確行為只是類(lèi)能夠實(shí)現要求的功能的基礎,類(lèi)成員函數間的作用和類(lèi)之間的服務(wù)調用是單元測試無(wú)法確定的。因此,需要進(jìn)行面向對象的集成測試。具體的測試方法在面向對象的集成測試中介紹。需要著(zhù)重聲明,測試類(lèi)的功能,不能僅滿(mǎn)足于代碼能無(wú)錯運行或被測試類(lèi)能提供的功能無(wú)錯,應該以所做的OOD結果為依據,檢測類(lèi)提供的功能是否滿(mǎn)足設計的要求,是否有缺陷。必要時(shí)(如通過(guò)OOD結仍不清楚明確的地方)還應該參照OOA的結果,以之為最終標準。
八面向對象的單元測試(OO Unit Test)
傳統的單元測試是針對程序的函數、過(guò)程或完成某一定功能的程序塊。沿用單元測試的概念,實(shí)際測試類(lèi)成員函數。一些傳統的測試方法在面向對象的單元測試中都可以使用。如等價(jià)類(lèi)劃分法,因果圖法,邊值分析法,邏輯覆蓋法,路徑分析法,程序插裝法等等,方法的具體實(shí)現參見(jiàn)[6]。單元測試一般建議由程序員完成。
用于單元級測試進(jìn)行的測試分析(提出相應的測試要求)和測試用例(選擇適當的輸入,達到測試要求),規模和難度等均遠小于后面將介紹的對整個(gè)系統的測試分析和測試用例,而且強調對語(yǔ)句應該有100%的執行代碼覆蓋率。在設計測試用例選擇輸入數據時(shí),可以基于以下兩個(gè)假設:
1. 如果函數(程序)對某一類(lèi)輸入中的一個(gè)數據正確執行,對同類(lèi)中的其他輸入也能正確執行。該假設的思想可參見(jiàn)[6]中介紹的等價(jià)類(lèi)劃分。
2. 如果函數(程序)對某一復雜度的輸入正確執行,對更高復雜度的輸入也能正確執行。例如需要選擇字符串作為輸入時(shí),基于本假設,就無(wú)須計較于字符串的長(cháng)度。除非字符串的長(cháng)度是要求固定的,如IP地址字符串。
在面向對象程序中,類(lèi)成員函數通常都很小,功能單一,函數的間調用頻繁,容易出現一些不宜發(fā)現的錯誤。例如:
· if (-1==write (fid, buffer, amount)) error_out();
該語(yǔ)句沒(méi)有全面檢查write()的返回值,無(wú)意中斷然假設了只有數據被完全寫(xiě)入和沒(méi)有寫(xiě)入兩種情況。當測試也忽略了數據部分寫(xiě)入的情況,就給程序遺留了隱患。
· 按程序的設計,使用函數strrchr()查找最后的匹配字符,但誤程序中寫(xiě)成了函數strchr(),使程序功能實(shí)現時(shí)查找的是第一個(gè)匹配字符。
· 程序中將if (strncmp(str1,str2,strlen(str1)))誤寫(xiě)成了
if (strncmp(str1,str2,strlen(str2)))。如果測試用例中使用的數據str1和str2長(cháng)度一樣,就無(wú)法檢測出。
因此,在做測試分析和設計測試用例時(shí),應該注意面向對象程序的這個(gè)特點(diǎn),仔細的進(jìn)行測試分析和設計測試用例,尤其是針對以函數返回值作為條件判斷選擇,字符串操作等情況。
面向對象編程的特性使得對成員函數的測試,又不完全等同于傳統的函數或過(guò)程測試。尤其是繼承特性和多態(tài)特性,使子類(lèi)繼承或過(guò)載的父類(lèi)成員函數出現了傳統測試中未遇見(jiàn)的問(wèn)題。在[7]中,Brian Marick 給出了二方面的考慮:
1. 繼承的成員函數是否都不需要測試?
根據[7]中的論述,對父類(lèi)中已經(jīng)測試過(guò)的成員函數,兩種情況需要在子類(lèi)中重新測試:a)繼承的成員函數在子類(lèi)中做了改動(dòng);b)成員函數調用了改動(dòng)過(guò)的成員函數的部分。例如:
假設父類(lèi)Bass有兩個(gè)成員函數:Inherited()和Redefined(),子類(lèi)Derived只對Redefined()做了改動(dòng)?! erived::Redefined()顯然需要重新測試。對于Derived::Inherited(),如果它有調用Redefined()的語(yǔ)句(如:x=x/Redefined()),就需要重新測試,反之,無(wú)此必要。
2. 對父類(lèi)的測試是否能照搬到子類(lèi)?
援用上面的假設,Base::Redefined()和Derived::Redefined()已經(jīng)是不同的成員函數,它們有不同的服務(wù)說(shuō)明和執行。對此,照理應該對 Derived::Redefined()重新測試分析,設計測試用例。但由于面向對象的繼承使得兩個(gè)函數有相似,故只需在 Base::Redefined()的測試要求和測試用例上添加對Derived::Redfined()新的測試要求和增補相應的測試用例。例如:
Base::Redefined()含有如下語(yǔ)句
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()的測試只需做如下改動(dòng):將value==0的測試結果期望改動(dòng);增加value==88的測試。
多態(tài)有幾種不同的形式,如參數多態(tài),包含多態(tài),過(guò)載多態(tài)。包含多態(tài)和過(guò)載多態(tài)在面向對象語(yǔ)言中通常體現在子類(lèi)與父類(lèi)的繼承關(guān)系,對這兩種多態(tài)的測試參見(jiàn)上述對父類(lèi)成員函數繼承和過(guò)載的論述。包含多態(tài)雖然使成員函數的參數可有多種類(lèi)型,但通常只是增加了測試的繁雜。對具有包含多態(tài)的成員函數測試時(shí),只需要在原有的測試分析和基礎上擴大測試用例中輸入數據的類(lèi)型的考慮。對類(lèi)為粒度進(jìn)行面向對象的單元測試,可參考[10]中關(guān)于如何從MtSS生成測試用例的說(shuō)明。
九面向對象的集成測試(OO Integrate Test)
傳統的集成測試,是由底向上通過(guò)集成完成的功能模塊進(jìn)行測試,一般可以在部分程序編譯完成的情況下進(jìn)行。而對于面向對象程序,相互調用的功能是散布在程序的不同類(lèi)中,類(lèi)通過(guò)消息相互作用申請和提供服務(wù)。類(lèi)的行為與它的狀態(tài)密切相關(guān),狀態(tài)不僅僅是體現在類(lèi)數據成員的值,也許還包括其他類(lèi)中的狀態(tài)信息。由此可見(jiàn),類(lèi)相互依賴(lài)極其緊密,根本無(wú)法在編譯不完全的程序上對類(lèi)進(jìn)行測試。所以,面向對象的集成測試通常需要在整個(gè)程序編譯完成后進(jìn)行。此外,面向對象程序具有動(dòng)態(tài)特性,程序的控制流往往無(wú)法確定,因此也只能對整個(gè)編譯后的程序做基于黑盒子的集成測試。
面向對象的集成測試能夠檢測出相對獨立的單元測試無(wú)法檢測出的那些類(lèi)相互作用時(shí)才會(huì )產(chǎn)生的錯誤?;趩卧獪y試對成員函數行為正確性的保證,集成測試只關(guān)注于系統的結構和內部的相互作用。面向對象的集成測試可以分成兩步進(jìn)行:先進(jìn)行靜態(tài)測試,再進(jìn)行動(dòng)態(tài)測試。
靜態(tài)測試主要針對程序的結構進(jìn)行,檢測程序結構是否符合設計要求?,F在流行的一些測試軟件都能提供一種稱(chēng)為"可逆性工程"的功能,即通過(guò)原程序得到類(lèi)關(guān)系圖和函數功能調用關(guān)系圖,例如International Software Automation 公司的Panorama-2 for Windows95、Rational公司的Rose C++ Analyzer等,將"可逆性工程"得到的結果與OOD的結果相比較,檢測程序結構和實(shí)現上是否有缺陷。換句話(huà)說(shuō),通過(guò)這種方法檢測OOP是否達到了設計要求。
動(dòng)態(tài)測試設計測試用例時(shí),通常需要上述的功能調用結構圖、類(lèi)關(guān)系圖或者實(shí)體關(guān)系圖為參考,確定不需要被重復測試的部分,從而優(yōu)化測試用例,減少測試工作量,使得進(jìn)行的測試能夠達到一定覆蓋標準。測試所要達到的覆蓋標準可以是:達到類(lèi)所有的服務(wù)要求或服務(wù)提供的一定覆蓋率;依據類(lèi)間傳遞的消息,達到對所有執行線(xiàn)程的一定覆蓋率;達到類(lèi)的所有狀態(tài)的一定覆蓋率等。同時(shí)也可以考慮使用現有的一些測試工具來(lái)得到程序代碼執行的覆蓋率。
具體設計測試用例,可參考下列步驟:
1. 先選定檢測的類(lèi),參考OOD分析結果,仔細出類(lèi)的狀態(tài)和相應的行為,類(lèi)或成員函數間傳遞的消息,輸入或輸出的界定等。
2. 確定覆蓋標準。
3. 利用結構關(guān)系圖確定待測類(lèi)的所有關(guān)聯(lián)。
4. 根據程序中類(lèi)的對象構造測試用例,確認使用什么輸入激發(fā)類(lèi)的狀態(tài)、使用類(lèi)的服務(wù)和期望產(chǎn)生什么行為等。
值得注意,設計測試用例時(shí),不但要設計確認類(lèi)功能滿(mǎn)足的輸入,還應該有意識的設計一些被禁止的例子,確認類(lèi)是否有不合法的行為產(chǎn)生,如發(fā)送與類(lèi)狀態(tài)不相適應的消息,要求不相適應的服務(wù)等。根據具體情況,動(dòng)態(tài)的集成測試,有時(shí)也可以通過(guò)系統測試完成。
十面向對象的系統測試(OO System Test)
通過(guò)單元測試和集成測試,僅能保證軟件開(kāi)發(fā)的功能得以實(shí)現。但不能確認在實(shí)際運行時(shí),它是否滿(mǎn)足用戶(hù)的需要,是否大量存在實(shí)際使用條件下會(huì )被誘發(fā)產(chǎn)生錯誤的隱患。為此,對完成開(kāi)發(fā)的軟件必須經(jīng)過(guò)規范的系統測試。換個(gè)角度說(shuō),開(kāi)發(fā)完成的軟件僅僅是實(shí)際投入使用系統的一個(gè)組成部分,需要測試它與系統其他部分配套運行的表現,以保證在系統各部分協(xié)調工作的環(huán)境下也能正常工作。在后面對ZXM10收發(fā)臺系統測試的敘述可以看到,其他的系統設備(如監控臺,圖象臺,E1接入設備,攝像頭等)如何配合收發(fā)臺的系統測試。
系統測試應該盡量搭建與用戶(hù)實(shí)際使用環(huán)境相同的測試平臺,應該保證被測系統的完整性,對臨時(shí)沒(méi)有的系統設備部件,也應有相應的模擬手段。系統測試時(shí),應該參考OOA分析的結果,對應描述的對象、屬性和各種服務(wù),檢測軟件是否能夠完全"再現"問(wèn)題空間。系統測試不僅是檢測軟件的整體行為表現,從另一個(gè)側面看,也是對軟件開(kāi)發(fā)設計的再確認。
這里說(shuō)的系統測試是對測試步驟的抽象描述。它體現的具體測試內容包括:
· 功能測試:測試是否滿(mǎn)足開(kāi)發(fā)要求,是否能夠提供設計所描述的功能,是否用戶(hù)的需求都得到滿(mǎn)足。功能測試是系統測試最常用和必須的測試,通常還會(huì )以正式的軟件說(shuō)明書(shū)為測試標準。
· 強度測試:測試系統的能力最高實(shí)際限度,即軟件在一些超負荷的情況,功能實(shí)現情況。如要求軟件某一行為的大量重復、輸入大量的數據或大數值數據、對數據庫大量復雜的查詢(xún)等。
· 性能測試:測試軟件的運行性能。這種測試常常與強度測試結合進(jìn)行,需要事先對被測軟件提出性能指標,如傳輸連接的最長(cháng)時(shí)限、傳輸的錯誤率、計算的精度、記錄的精度、響應的時(shí)限和恢復時(shí)限等。
· 安全測試:驗證安裝在系統內的保護機構確實(shí)能夠對系統進(jìn)行保護,使之不受各種非常的干擾。安全測試時(shí)需要設計一些測試用例試圖突破系統的安全保密措施,檢驗系統是否有安全保密的漏洞。
· 恢復測試:采用人工的干擾使軟件出錯,中斷使用,檢測系統的恢復能力,特別是通訊系統?;謴蜏y試時(shí),應該參考性能測試的相關(guān)測試指標。
· 可用性測試:測試用戶(hù)是否能夠滿(mǎn)意使用。具體體現為操作是否方便,用戶(hù)界面是否友好等。
· 安裝/卸載測試(install/uninstall test)等等。
系統測試需要對被測的軟件結合需求分析做仔細的測試分析,建立測試用例。
十一參考文獻(Reference)
[1] 蔡希堯陳平,面向對象技術(shù),西安電子科技大學(xué)出版社,1993年11 月
[2] Coad, P. And Yourdon, E. , "Object-Oriented Analysis", Yourdon Press, 1989
[3] 湯庸,軟件工程方法學(xué)及應用,中國三峽出版社,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] 鄭人杰,計算機軟件測試技術(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