姚紅+李茂斌
摘要:在面向?qū)ο蟪绦蛟O(shè)計(jì)中,動態(tài)多態(tài)性的引入為程序的可復(fù)用性和可擴(kuò)充性提供了極大的便利,但同時(shí)也為程序的測試引入了一般測試方法無法很好應(yīng)對的難題。在該文中,作者基于實(shí)踐,提出了一種針對面向?qū)ο髣討B(tài)多態(tài)性的測試方法。該方法從靜態(tài)分析入手,首先從被測程序中識別出需要進(jìn)行動態(tài)多態(tài)性測試的代碼,以此建立被測程序的動態(tài)多態(tài)性測試表,然后對該測試表進(jìn)行分析,并最終在此基礎(chǔ)上生成測試用例。該方法主要針對面向?qū)ο髣討B(tài)多態(tài)性的測試,可以作為一般面向?qū)ο筌浖y試的補(bǔ)充。
關(guān)鍵詞:面向?qū)ο?;動態(tài)多態(tài)性;軟件測試
中圖分類號:TP311 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2017)06-0138-02
1 概述
多態(tài)性是面向?qū)ο蟮闹匾卣?,其與封裝性和繼承性并稱為面向?qū)ο蟪绦蛟O(shè)計(jì)的三大特性。多態(tài)性的定義為:指允許不同的類的對象對同一消息做出響應(yīng),即同一消息可以根據(jù)發(fā)送對象的不同而采取多種不同的行為方式。簡單來說就是“一個(gè)對外的接口,有多個(gè)內(nèi)在的實(shí)現(xiàn)方法”。多態(tài)性按運(yùn)行時(shí)刻可劃分為靜態(tài)多態(tài)性和動態(tài)多態(tài)性。靜態(tài)多態(tài)性是指定義有一個(gè)類的同名函數(shù),它們根據(jù)參數(shù)的類型和個(gè)數(shù)不同進(jìn)行語義區(qū)別,其主要通過函數(shù)的重載(Overload)和運(yùn)算符重載來實(shí)現(xiàn)的,這種多態(tài)性在程序編譯時(shí)系統(tǒng)就能識別調(diào)用的是哪個(gè)函數(shù),也叫做靜態(tài)綁定。動態(tài)多態(tài)性是指在程序執(zhí)行前,系統(tǒng)無法根據(jù)函數(shù)名和參數(shù)來確定要調(diào)用哪個(gè)函數(shù),必須在程序執(zhí)行過程中,根據(jù)執(zhí)行的具體情況來動態(tài)的確定,它是通過類的繼承關(guān)系和虛函數(shù)重寫(Override)來實(shí)現(xiàn)的,這種多態(tài)性在程序編譯時(shí)系統(tǒng)無法識別調(diào)用的是哪個(gè)函數(shù),直到運(yùn)行時(shí)刻調(diào)用時(shí)才能確定,故又叫做動態(tài)綁定。
在對具有多態(tài)性的程序進(jìn)行測試時(shí),靜態(tài)多態(tài)性的代碼我們可以理解為多個(gè)名字相同的類成員函數(shù),使用一般的測試方法就可以對其進(jìn)行測試。相對于靜態(tài)多態(tài)性,對動態(tài)多態(tài)性的程序代碼進(jìn)行測試則顯得困難了許多,其中最主要的難點(diǎn)是測試用例的設(shè)計(jì),由于動態(tài)多態(tài)性是在程序執(zhí)行時(shí)才確定具體哪個(gè)函數(shù)被調(diào)用,所以這要求測試人員在設(shè)計(jì)測試用例時(shí)要用模擬程序運(yùn)行的動態(tài)思維來考慮,才能使所有可能的函數(shù)調(diào)用均被測試用例覆蓋,這無疑是一個(gè)很高的要求。
本人在多個(gè)工程項(xiàng)目軟件測試經(jīng)驗(yàn)教訓(xùn)基礎(chǔ)上,參考了多種面向?qū)ο鬁y試策略,提出了一種針對面向?qū)ο髣討B(tài)多態(tài)性的測試方法,這種方法從靜態(tài)分析入手,首先從被測程序中識別出需要進(jìn)行動態(tài)多態(tài)性測試的代碼,以此建立被測程序的動態(tài)多態(tài)性測試表,然后對該測試表進(jìn)行分析,并最終在此基礎(chǔ)上生成測試用例。這種方法能很好地解決動態(tài)多態(tài)性代碼的測試問題。
2靜態(tài)分析
2.1 動態(tài)多態(tài)性識別
要在諸多程序代碼中識別出哪部分代碼需要進(jìn)行動態(tài)多態(tài)性測試,就要對動態(tài)多態(tài)性的形成機(jī)制有深刻的理解。簡單地說,動態(tài)多態(tài)性的形成需要三個(gè)基本條件:繼承、虛函數(shù)重寫和指向子類對象的父類指針,其中繼承是動態(tài)多態(tài)性的基礎(chǔ),只有有繼承關(guān)系的父類和子類之間才有可能形成動態(tài)多態(tài)性;虛函數(shù)重寫是指父類定義實(shí)現(xiàn)一個(gè)虛函數(shù)接口,子類繼承父類的接口并對該虛函數(shù)進(jìn)行重寫,這是動態(tài)多態(tài)性形成的技術(shù)關(guān)鍵;指向子類對象的父類指針是指將一個(gè)子類的對象賦予一個(gè)父類的指針,并使用該指針調(diào)用重寫的虛函數(shù),這樣在程序運(yùn)行時(shí)系統(tǒng)就會調(diào)用指針指向的虛函數(shù)表所記錄的子類的函數(shù),而不是父類的函數(shù)。
下面以一段代碼來說明如何識別程序代碼中的動態(tài)多態(tài)性。
class A {
virtual void fun1(){...}; //此處省略處理描述
virtual void fun2(){...};
};
class B : public A {
void fun1(){...}; //重寫父類的虛函數(shù)fun1
void fun2(){...}; //重寫父類的虛函數(shù)fun2
};
class C : public A {
void fun2(){...}; //重寫父類的虛函數(shù)fun2
};
void Testfun(int i_flg)
{
A *a;
switch(i_flg) {
case 1:
a = new B; break;
case 2:
a = new C; break;
default:
a = new A; break;
}
a->fun1();
a->fun2();
}
由以上代碼我們可以看出類A為父類,類B和類C為類A的子類,并分別重寫了父類A的虛函數(shù),在函數(shù)Testfun(int i_flg)代碼的最后使用了父類指針完成虛函數(shù)的調(diào)用,具備了動態(tài)多態(tài)性的三個(gè)基本條件,那這段代碼應(yīng)該如何識別分析呢?經(jīng)過簡單分析我們不難發(fā)現(xiàn),當(dāng)輸入變量i_flg的值為1時(shí),指針a指向的為類B的對象,此時(shí)a->fun1()和a->fun2()調(diào)用均為類B的fun1和fun2調(diào)用,產(chǎn)生了動態(tài)多態(tài)性;當(dāng)i_flg的值為2時(shí),指針a指向的為類C的對象,但是情況有點(diǎn)復(fù)雜,由于類C沒有重寫父類的虛函數(shù)fun1,故a->fun1()執(zhí)行的是類A的fun1調(diào)用,而a->fun2()則為類C的fun2調(diào)用,部分產(chǎn)生了動態(tài)多態(tài)性;當(dāng)i_flg的值為1和2之外的值時(shí),指針a指向的為類A的對象,此時(shí)a->fun1()和a->fun2()均為類A的函數(shù)調(diào)用,沒有產(chǎn)生動態(tài)多態(tài)性。在實(shí)際測試時(shí),被測代碼肯定比以上示例代碼要復(fù)雜得多,但動態(tài)多態(tài)性識別的思路和方法是基本一致的。
2.2動態(tài)多態(tài)性測試表的建立和分析
在對被測程序代碼進(jìn)行動態(tài)多態(tài)性識別時(shí),需要同步進(jìn)行的工作就是建立動態(tài)多態(tài)性測試表。測試表的作用為對動態(tài)多態(tài)性識別結(jié)果的記錄,為下一步測試表分析和生成測試用例提供支撐。測試表記錄的內(nèi)容可以由測試人員根據(jù)項(xiàng)目實(shí)際情況自由裁定,但應(yīng)該至少包括以下幾條內(nèi)容:
1)產(chǎn)生位置。該條用于記錄和定位要進(jìn)行動態(tài)多態(tài)性測試的代碼段,比如:test.cpp/testfun(int i_flg)。
2)先決條件和影響因素。該條用于記錄動態(tài)多態(tài)性產(chǎn)生的各種前提條件和影響因素,其作用為在設(shè)計(jì)測試用例時(shí)可作為測試的約束和輸入。
3)表征代碼和期望執(zhí)行代碼。表征代碼即為產(chǎn)生動態(tài)多態(tài)性的源程序代碼,如以上示例代碼中的a->fun1()和a->fun2()(記錄時(shí)指針a前應(yīng)加上 A *以標(biāo)識其類型,以免測試表項(xiàng)增多以后產(chǎn)生混淆),期望執(zhí)行代碼為表征代碼在程序運(yùn)行時(shí)應(yīng)該執(zhí)行的代碼,如a->fun1()在i_flg為1時(shí)的期望執(zhí)行代碼為B::fun1()。
在完成動態(tài)多態(tài)性測試表的建立后,下一步的工作就是對測試表進(jìn)行分析。測試表的分析工作就是對測試表項(xiàng)按其復(fù)雜性進(jìn)行整理、分解或合并的過程,以期測試人員能根據(jù)它更方便的設(shè)計(jì)測試用例。測試表分析的理想結(jié)果是測試人員根據(jù)該表設(shè)計(jì)出較少的測試用例完成動態(tài)多態(tài)性測試的最大覆蓋。當(dāng)然,當(dāng)建立起的測試表項(xiàng)較少或影響動態(tài)多態(tài)性的因素較少比較容易設(shè)計(jì)測試用例時(shí),測試人員可以跳過測試表分析直接開始測試用例設(shè)計(jì)。
3 測試設(shè)計(jì)
對動態(tài)多態(tài)性的測試設(shè)計(jì)包括測試用例設(shè)計(jì)和測試程序設(shè)計(jì)。在經(jīng)過前文介紹的動態(tài)多態(tài)性識別、動態(tài)多態(tài)性測試表的建立和分析一系列工作后,測試用例的設(shè)計(jì)就變得簡單了:由測試表中的“先決條件和影響因素”一條細(xì)化、分解、加工即可生成測試用例的測試準(zhǔn)備和測試輸入;根據(jù)測試表中的“表征代碼和期望執(zhí)行代碼”一條可以設(shè)計(jì)測試用例中各種分支下的期望執(zhí)行過程和期望結(jié)果。至此,一個(gè)動態(tài)多態(tài)性測試用例的基本要素均已具備,接下來要做的就是將測試用例文檔化并列入單元或集成測試說明的相應(yīng)章節(jié)中,在被測程序進(jìn)行類測試或類集成測試時(shí)一并進(jìn)行測試。
測試程序的設(shè)計(jì)一般包括測試驅(qū)動、測試樁和輔助測試模塊的設(shè)計(jì)。測試驅(qū)動和測試樁在一般的軟件測試中均會用到,對于動態(tài)多態(tài)性的代碼也無太大區(qū)別,此處就不再多做描述。對于輔助測試模塊的設(shè)計(jì),在這里簡單介紹一下本人在進(jìn)行動態(tài)多態(tài)性測試時(shí)常用的一種輔助手段—-動態(tài)窗口的設(shè)計(jì)方法,動態(tài)窗口的設(shè)計(jì)思想就是給被測類開一個(gè)窗口,在不破壞類封裝性的前提下能方便的觀察在測試過程中當(dāng)前類的類型、屬性及狀態(tài)等信息。其實(shí)現(xiàn)方式就是在父類中定義用作窗口的虛函數(shù),并在子類繼承并重寫該窗口函數(shù),這樣這個(gè)窗口就具有了動態(tài)多態(tài)性。動態(tài)窗口在測試過程中能提供很大的幫助,它能幫助測試人員方便地監(jiān)視測試時(shí)執(zhí)行過程和類的狀態(tài)改變是否與預(yù)期的一致。值得注意的是在窗口函數(shù)編寫過程中應(yīng)遵循一個(gè)原則,就是窗口函數(shù)是一個(gè)觀察窗口,它不能有任何會改變類屬性和狀態(tài)的操作,也不可與類的方法有嵌套條用關(guān)系,這對被測程序保持其代碼原始性至關(guān)重要。
4 結(jié)束語
總的來說,這種針對面向?qū)ο髣討B(tài)多態(tài)性的測試方法關(guān)鍵步驟就是識別出動態(tài)多態(tài)性代碼段,建立起動態(tài)多態(tài)性測試表,然后根據(jù)測試表的內(nèi)容產(chǎn)生測試用例。這種方法在應(yīng)對多影響因素、有復(fù)雜調(diào)用關(guān)系的動態(tài)多態(tài)性代碼時(shí)尤為有效,它能幫助測試人員理清發(fā)生動態(tài)多態(tài)性調(diào)用時(shí)程序的實(shí)際執(zhí)行路徑和影響因素,方便測試人員以較少的測試用例來達(dá)到最大的動態(tài)多態(tài)性測試覆蓋。本人使用該方法對多個(gè)有動態(tài)多態(tài)性的軟件進(jìn)行了類測試和類集成測試,均達(dá)到了比較滿意的效果。
參考文獻(xiàn):
[1] 斯科瑞.面向?qū)ο笤O(shè)計(jì)原理與模式[M].北京:清華大學(xué)出版社,2009.
[2] Erich Gamma,Richard Helm,Ralph Johnson.設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)[M]. 北京:機(jī)械工業(yè)出版社,2007.
[3] 周建儒,余美璘.面向?qū)ο筇卣髦鄳B(tài)性的分析[J].科技信息,2009(35).
[4] 和力,吳麗賢.關(guān)于C++虛函數(shù)底層實(shí)現(xiàn)機(jī)制的研究與分析[J].計(jì)算機(jī)工程與設(shè)計(jì),2008(10).
[5] 郭滔.面向?qū)ο筌浖y試技術(shù)研究[J].科技信息,2011(3).
[6] 徐虹.面向?qū)ο蟮能浖y試模型及策略研究[J].計(jì)算機(jī)與現(xiàn)代化,2005(3).
[7] 趙榮利,崔志明,陳建明.面向?qū)ο筌浖y試技術(shù)的研究與應(yīng)用[J].計(jì)算機(jī)技術(shù)與發(fā)展,2007(1).