李莉 張青
摘要:軟件的安全性和可靠性在今天越來(lái)越受到重視,由于軟件邊界值處理不當(dāng)引起的問(wèn)題層出不窮,該文結(jié)合若干邊界測(cè)試的典型案例,從循環(huán)邊界、數(shù)據(jù)值邊界、數(shù)據(jù)量邊界、狀態(tài)轉(zhuǎn)換邊界等多個(gè)角度闡述軟件相關(guān)邊界問(wèn)題產(chǎn)生原因,總結(jié)軟件中的邊界處理要點(diǎn),為軟件設(shè)計(jì)提供參考。
關(guān)鍵詞:軟件測(cè)試;邊界測(cè)試
中圖分類號(hào):TP311 ? ? ?文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1009-3044(2021)31-0132-03
1 邊界測(cè)試概述
隨著大數(shù)據(jù)和人工智能時(shí)代的來(lái)臨,各種軟件在人們的工作和生活中承擔(dān)的任務(wù)越來(lái)越重要,隨之而來(lái),對(duì)軟件的可靠性要求也越來(lái)越高。軟件測(cè)試是保障軟件安全可靠性的一種重要手段,測(cè)試類型從最初的功能測(cè)試,擴(kuò)展和細(xì)化到現(xiàn)在的功能、性能測(cè)試、數(shù)據(jù)測(cè)試、接口測(cè)試、邊界測(cè)試、余量測(cè)試、安全性、可靠性測(cè)試等等眾多類型。
由測(cè)試數(shù)據(jù)統(tǒng)計(jì)得知,大量的軟件錯(cuò)誤是發(fā)生在輸入或輸出的邊界上,而不是發(fā)生在輸入輸出范圍的內(nèi)部[1-2],但是在軟件設(shè)計(jì)和程序編寫過(guò)程中,設(shè)計(jì)師常常對(duì)需求中的輸入或輸出邊界重視不夠,導(dǎo)致出現(xiàn)各種錯(cuò)誤,因此針對(duì)各種邊界情況開展測(cè)試,我們可以查找出更多的軟件錯(cuò)誤[3]。
2 邊界測(cè)試方法
邊界值分析是邊界測(cè)試的主要測(cè)試方法,它是對(duì)等價(jià)類分析方法的一種補(bǔ)充。開展軟件邊界測(cè)試首先需要確定邊界情況,然后選取正好等于、剛剛大于或剛剛小于邊界的值作為測(cè)試數(shù)據(jù),而不是選取等價(jià)類中的典型值或任意值作為測(cè)試數(shù)據(jù)[4]。常用的邊界值分析方法有三點(diǎn)法、五點(diǎn)法、七點(diǎn)法等等,分別針對(duì)一至多個(gè)邊界點(diǎn),選取相應(yīng)邊界值開展測(cè)試,原理比較簡(jiǎn)單。
3 邊界測(cè)試點(diǎn)選取
一旦邊界點(diǎn)選定,相應(yīng)的邊界值也隨之確定,測(cè)試數(shù)據(jù)也順利生成,看上去非常簡(jiǎn)單。但是實(shí)際操作中,邊界問(wèn)題還是層出不窮,其原因就在于:
1)設(shè)計(jì)師并未意識(shí)到當(dāng)前數(shù)據(jù)是有邊界要求的;
2)有些邊界要求不體現(xiàn)在軟件文檔要求中,而是隨著設(shè)計(jì)師的程序編寫過(guò)程不斷產(chǎn)生的;
3)需求隱含了一些功能邊界要求,但是這些要求需要設(shè)計(jì)師在領(lǐng)會(huì)整個(gè)系統(tǒng)流程的基礎(chǔ)上總結(jié)概括得出,如果對(duì)系統(tǒng)理解不全面,可能會(huì)漏掉對(duì)相關(guān)邊界的處理。
綜上所述,對(duì)于軟件測(cè)試人員來(lái)說(shuō),邊界測(cè)試的重點(diǎn)在于尋找被設(shè)計(jì)師忽略或理解錯(cuò)誤的數(shù)據(jù)點(diǎn)。因此,邊界測(cè)試的難點(diǎn)不在于測(cè)試執(zhí)行,而在于測(cè)試對(duì)象即測(cè)試點(diǎn)的發(fā)現(xiàn)和選取。
通常,軟件邊界測(cè)試分為數(shù)據(jù)值邊界和數(shù)據(jù)量邊界:數(shù)據(jù)值邊界是指有明確邊界要求的數(shù)據(jù),這些數(shù)據(jù)有些在軟件需求規(guī)格說(shuō)明或者詳細(xì)設(shè)計(jì)中特別提出,有些是程序內(nèi)部自定義數(shù)據(jù),需要根據(jù)其含義自行界定其邊界;數(shù)據(jù)量邊界包括數(shù)據(jù)長(zhǎng)度邊界、數(shù)據(jù)容量邊界(存儲(chǔ)區(qū)容量、堆棧容量等)、通信通道容量邊界等等,這些邊界要求通常隱含在接口說(shuō)明或硬件說(shuō)明中;還有一些邊界要求并沒(méi)有在文檔中出現(xiàn),需要測(cè)試人員結(jié)合軟件文檔和程序上下文推導(dǎo)得出。
在這些顯性或隱性的邊界點(diǎn)的處理上出現(xiàn)了不少軟件問(wèn)題,下面我們結(jié)合具體案例介紹。
4 邊界測(cè)試典型案例分析
4.1 循環(huán)邊界
循環(huán)邊界是比較常見的測(cè)試邊界,通常包括:
1)有明確要求的循環(huán)次數(shù);
2)與時(shí)序有關(guān)的循環(huán)。
案例1:
需求要求某個(gè)操作循環(huán)執(zhí)行3次。
循環(huán)變量初始值times=0,軟件實(shí)現(xiàn)如下圖:
從圖中代碼可見,由于while判斷times終止值為3,顯然循環(huán)次數(shù)已達(dá)到4次,超過(guò)3次循環(huán)的要求。
這種循環(huán)數(shù)據(jù)邊界的問(wèn)題在單元測(cè)試中是頻發(fā)問(wèn)題,設(shè)計(jì)師在編寫循環(huán)處理語(yǔ)句的時(shí)候需要嚴(yán)格對(duì)照需求的要求,特別注意循環(huán)的起始值和結(jié)束值的處理,以避免循環(huán)次數(shù)超限。
案例2:
需求要求每20ms執(zhí)行子程序Calu_20(),采用前一拍引力進(jìn)行當(dāng)前拍位置計(jì)算,程序初始值Gx0,Gx1的值均為0。子程序?qū)崿F(xiàn)如下圖所示:
由以上程序可得:
第1拍20ms當(dāng)前位置PX1計(jì)算,使用的Gx0值為初始值0;
第2拍20ms當(dāng)前位置PX1計(jì)算,使用的Gx0值為第1拍中Gx1賦予它的值,也是0;
第3拍20ms 當(dāng)前位置PX1計(jì)算,使用的Gx0值為第2拍中Gx1賦予它的值,即Gx0=Gx0_1_Step;
由分析可知,由于語(yǔ)句②的位置錯(cuò)誤,導(dǎo)致當(dāng)前位置PX1計(jì)算時(shí)使用的其實(shí)是前2拍的引力值,程序應(yīng)將語(yǔ)句②放在語(yǔ)句①之前執(zhí)行,才能保證時(shí)序的正確。修改后的程序如下圖所示:
在嵌入式軟件中,常常用中斷去執(zhí)行一些與時(shí)序有關(guān)的計(jì)算或控制,定時(shí)中斷由于定期不斷執(zhí)行,因此我們可以把它看作是一種特殊的循環(huán)。此時(shí),我們需要格外注意從上一次中斷到下一次中斷的切換執(zhí)行,通常時(shí)序錯(cuò)誤都發(fā)生在切換的邊界。例如上面這個(gè)例子,如果2拍引力值的偏差較小,這種錯(cuò)誤很難在動(dòng)態(tài)測(cè)試中發(fā)現(xiàn),通常只有通過(guò)代碼走讀才能分析得出。
4.2 數(shù)據(jù)域邊界
數(shù)據(jù)域的邊界一般包括:
1)數(shù)組范圍的邊界;
2)數(shù)據(jù)類型的邊界。
案例3:
軟件需求要求程序采集每20ms電壓測(cè)量值,通過(guò)累積每20ms的電壓差值,計(jì)算得出2s電壓差值,程序?qū)崿F(xiàn)如下:
由以上程序可知,數(shù)組DY[]中存放的是每20ms的電壓差值,程序需要計(jì)算的是2s累計(jì)的電壓差值,共100個(gè)差值就應(yīng)該涉及到101個(gè)電壓測(cè)量值。但是由于程序?qū)㈦妷簻y(cè)量值數(shù)組DY[]大小定義為100,所以該數(shù)組大小不夠,應(yīng)定義為101個(gè)元素。此外,程序循環(huán)到i=99時(shí),DY[]數(shù)組下標(biāo)已引用到100,而數(shù)組的下標(biāo)最大應(yīng)該比數(shù)組大小小1,因此,此處對(duì)數(shù)組的引用已溢出。
在數(shù)組的應(yīng)用上,出錯(cuò)頻率較高的是數(shù)組下標(biāo)邊界,特別是當(dāng)下標(biāo)用作循環(huán)變量時(shí),設(shè)計(jì)人員經(jīng)常容易忽略其范圍要求而超范圍使用下標(biāo)。
案例4:
軟件運(yùn)行環(huán)境為TMS320C5416,是16位的定點(diǎn)DSP,其中一段程序?qū)崿F(xiàn)門限的計(jì)算,具體見圖5:
在16位定點(diǎn)DSP中,Unsigned int類型數(shù)據(jù)表示范圍為0~65535,這段程序用到的三個(gè)變量都是Unsigned int類型。
設(shè)置PRI=90,Δd=50,則程序運(yùn)行計(jì)算時(shí),算到20*PRI*Δd時(shí),中間結(jié)果20*PRI*Δd的計(jì)算值已達(dá)到90000,超過(guò)了Unsigned int表示的最大范圍,數(shù)據(jù)溢出,中間結(jié)果由90000變成了24464,再經(jīng)過(guò)/200的運(yùn)算,最后計(jì)算結(jié)果為122,程序?qū)崿F(xiàn)錯(cuò)誤。
這是一個(gè)典型的白盒數(shù)據(jù)邊界測(cè)試問(wèn)題,此處進(jìn)行計(jì)算的代碼運(yùn)算執(zhí)行順序是從左到右,因此導(dǎo)致中間結(jié)果溢出。對(duì)于不同的編譯器,程序的運(yùn)算順序可能有所不同,因此無(wú)論是軟件設(shè)計(jì)人員還是測(cè)試人員,都應(yīng)當(dāng)深入了解程序運(yùn)行環(huán)境,深刻理解每種數(shù)據(jù)類型的表示范圍,避免數(shù)據(jù)超出類型表示范圍邊界。
4.3 數(shù)據(jù)量邊界
數(shù)據(jù)量邊界通常與硬件相關(guān),一般包括:
1)存儲(chǔ)區(qū)容量邊界;
2)堆棧容量邊界;
3)通信通道容量邊界;
4)信號(hào)有效范圍邊界。
案例5:
這是一個(gè)非常著名的案例,豐田汽車不響應(yīng)剎車而失控爆沖,該事件后有軟件專家對(duì)其控制軟件進(jìn)行了測(cè)試,以下是其中部分軟件缺陷描述:
豐田的軟件系統(tǒng)有兩塊相鄰的內(nèi)存塊。第一塊內(nèi)存區(qū)域存儲(chǔ)所有任務(wù)以及任務(wù)的運(yùn)行狀態(tài),稱為“堆棧(Stack)”,大小為4KB。與“堆?!毕噜彽膬?nèi)存中儲(chǔ)存了操作系統(tǒng)進(jìn)行任務(wù)分配的記錄。在某些情境下,如果任務(wù)及任務(wù)的運(yùn)行狀態(tài)數(shù)據(jù)很多,那么會(huì)往堆棧里寫入太多東西,如果大小超過(guò)4KB,那么就會(huì)錯(cuò)誤地寫入相鄰的內(nèi)存塊,即任務(wù)分配表,這種錯(cuò)誤被稱為“堆棧溢出”??梢韵胂?,一旦出現(xiàn)堆棧溢出,任務(wù)分配表內(nèi)容會(huì)被改寫,系統(tǒng)就會(huì)錯(cuò)誤地分配任務(wù),造成任務(wù)內(nèi)容、執(zhí)行次數(shù)的錯(cuò)亂,甚至某些任務(wù)直接被忽略[5]。
這是一個(gè)典型的堆棧使用超邊界問(wèn)題,這些問(wèn)題的產(chǎn)生通常是在軟件的系統(tǒng)規(guī)劃和設(shè)計(jì)階段沒(méi)有對(duì)后期使用作充分評(píng)估,導(dǎo)致內(nèi)存分配不夠引起的。類似的存儲(chǔ)容量、通信通道容量等也應(yīng)當(dāng)在系統(tǒng)設(shè)計(jì)初期就做好規(guī)劃,否則一旦使用中超出其容量邊界,會(huì)引起整個(gè)系統(tǒng)癱瘓等致命故障。
4.4 狀態(tài)轉(zhuǎn)換邊界
在軟件運(yùn)行過(guò)程中從一個(gè)狀態(tài)切換到另一個(gè)狀態(tài)也是一個(gè)重要的邊界。例如:有些軟件分階段運(yùn)行,包括測(cè)試態(tài)和正式狀態(tài),兩者會(huì)調(diào)用一些相同的函數(shù),靠外部信號(hào)來(lái)進(jìn)行狀態(tài)轉(zhuǎn)換。還有一些軟件,執(zhí)行時(shí)有明確的運(yùn)行狀態(tài),各狀態(tài)分工清楚,切換時(shí)機(jī)明確。
案例6:
某飛行軟件所控制的飛行階段明確分為一、二、三級(jí),一級(jí)關(guān)機(jī)后進(jìn)入二級(jí)飛行段,二級(jí)關(guān)機(jī)后進(jìn)入三級(jí)飛行段。在程序中,每級(jí)關(guān)機(jī)會(huì)讀取三次關(guān)機(jī)信號(hào),分別存儲(chǔ)于三塊不同地址的內(nèi)存中,程序需要對(duì)這三個(gè)地址中存放的關(guān)機(jī)信號(hào)進(jìn)行三取二的可靠性判斷。由于一、二、三級(jí)飛行按順序進(jìn)行,不會(huì)并行,因此設(shè)計(jì)師復(fù)用了三個(gè)地址存放三個(gè)級(jí)別飛行時(shí)段的關(guān)機(jī)信號(hào)。
需求要求一級(jí)關(guān)機(jī)的條件是收到0xA信號(hào);二級(jí)關(guān)機(jī)的條件是收到0xB信號(hào);三級(jí)關(guān)機(jī)的條件是收到0xC信號(hào)。
測(cè)試人員在一級(jí)關(guān)機(jī)時(shí)給出三個(gè)值為0xA,0xB,0xA,一級(jí)順利關(guān)機(jī),進(jìn)入二級(jí)飛行階段。一級(jí)轉(zhuǎn)二級(jí)時(shí),程序沒(méi)有將三個(gè)地址的數(shù)據(jù)清零,因此轉(zhuǎn)二級(jí)飛行時(shí),內(nèi)存中三個(gè)值為0xA,0xB,0xA,進(jìn)入二級(jí)后,測(cè)試人員給只給第一個(gè)地址賦值0xB,內(nèi)存中三個(gè)值為0xB,0xB,0xA,經(jīng)過(guò)三取二,得出當(dāng)前已收到0xB信號(hào)的結(jié)論,因此二級(jí)關(guān)機(jī)——但此時(shí)實(shí)際上程序剛收到一次關(guān)機(jī)信號(hào),另兩次關(guān)機(jī)信號(hào)還未發(fā)出。由于狀態(tài)轉(zhuǎn)換邊界處理不當(dāng),程序發(fā)生誤判,導(dǎo)致提早關(guān)機(jī)。
狀態(tài)轉(zhuǎn)換時(shí)涉及到的信息處理工作很多,一不小心就會(huì)有遺漏,導(dǎo)致程序出錯(cuò)。因此,設(shè)計(jì)師應(yīng)關(guān)注狀態(tài)轉(zhuǎn)換邊界,查看程序狀態(tài)轉(zhuǎn)換時(shí)涉及到的數(shù)據(jù)和控制信息,避免發(fā)生錯(cuò)誤。
4.5 輸出邊界
軟件的邊界測(cè)試不僅關(guān)注輸入邊界和硬件使用邊界,還應(yīng)結(jié)合外部接口要求,考慮輸出數(shù)據(jù)和信號(hào)的邊界。
例如:
1)DSP和FPGA交互時(shí),向?qū)Ψ捷敵龅臄?shù)據(jù)是否有值域要求。
2)軟件向硬件發(fā)出一些信號(hào)信息時(shí),考慮硬件是否有特殊要求,比如限幅等。
5 結(jié)束語(yǔ)
軟件在計(jì)算機(jī)系統(tǒng)中所占比重越來(lái)越大,相應(yīng)的軟件面臨的風(fēng)險(xiǎn)也越來(lái)越多,本文結(jié)合典型案例將軟件測(cè)試過(guò)程中發(fā)現(xiàn)的各種邊界問(wèn)題進(jìn)行了總結(jié)和歸納,為軟件設(shè)計(jì)和測(cè)試人員提供參考,以避免軟件邊界問(wèn)題,增強(qiáng)軟件的可靠性。
參考文獻(xiàn):
[1] 王軼辰,殷永峰,劉斌.航電設(shè)備軟件系統(tǒng)測(cè)試過(guò)程研究[J].測(cè)控技術(shù),2004,23(8):53-55,64.
[2] Jorgensen P C.軟件測(cè)試[M].韓柯,杜旭濤,譯.北京:機(jī)械工業(yè)出版社,2003.
[3] MOLLY_CICI.邊界值分析法--測(cè)試用例設(shè)計(jì)方法[EB/OL].[2020-10-18].https://blog.csdn.net/molly_cici/article/details/102626757.
[4] 劉暢,王軼辰,劉斌,等.軟件邊界組合測(cè)試的典型案例分析[J].計(jì)算機(jī)工程與應(yīng)用,2009,45(20):74-77.
[5] SCHWARZ.豐田栽了的原因[EB/OL].(2013-11-03)[2021-09-27].http://www.amobbs.com/thread-5557598-1-1.html.
【通聯(lián)編輯:謝媛媛】
收稿日期:2021-06-20
作者簡(jiǎn)介:李莉(1978—),女,江蘇啟東人,高級(jí)工程師,碩士,研究方向?yàn)檐浖こ?、軟件測(cè)試、軟件開發(fā)技術(shù);張青(1979—),男,江蘇啟東人,高級(jí)工程師,碩士,研究方向?yàn)檐浖こ?、軟件研發(fā)。