牛穎蓓, 左 蕓
(中國電子科技集團公司 第三十二研究所,上海 201808)
航天工程,包括運載火箭、衛(wèi)星、飛船和武器等型號都涉及巨大的投入、重要的使命乃至國家的安危[1]。特別是承擔過程控制、系統指揮、數據處理等關鍵任務的軟件,有大量是實時嵌入式軟件。嵌入式控制器既需要快速地完成復雜控制算法的運算,又需要很高的控制精度。DSPVC33由于具有高效的實時運算速度和強大的數據運算處理能力,越來越廣泛地應用于航空航天領域。伴隨著基于DSPVC33航天軟件可靠性要求越來越高,基于DSPVC33航天軟件的測試技術要求也越來越高。實時嵌入式軟件給軟件測試造成了很大的困難,使得軟件測試技術和方法的運用非常艱難,有時甚至是不可行的,因此選擇一種合適的測試技術和方法顯得尤為重要。
隨著國外芯片及傳感器的智能化、網絡化及微型化發(fā)展,使得采用虛擬儀器構建測試系統測試軟件應運而生,目前我國的測試技術正逐步向智能化、網絡化方向發(fā)展。
在軟件測試中,為了使得整個軟件得到多次多層的測試[2],發(fā)現存在于單元間接口的諸多問題,驗證單元接口的一致性、正確性而采用集成測試技術,集成測試采取系統性的技術,這是一個漸進的過程,從一個單元開始,逐步把單元集成為部件,把部件和部件集成為軟件配置項。在這個過程中,對接口的測試和對部件的測試交叉進行,從而使得整個軟件得到多層次的測試。根據航天型號軟件可靠性、安全性要求高,又有極特殊的運行環(huán)境,通過結合具體航天型號軟件研制實踐,形成基于DSPVC33航天型號軟件適用的集成測試技術和方法。
集成測試方法是進行單元模塊組裝的方法和步驟[3]。集成測試方法包含漸增式和非漸增式兩大類,漸增式測試又可分為自頂向下、自底向上和三明治集成3種方法。
把幾十甚至上百個單元聯接在一起,先分散測試,再集中起來一次完成組合和測試,對各個模塊測試結束為止,對整個程序進行組合時才能發(fā)現錯誤,需要構造驅動模塊和樁模塊。適用于在一個做得很好的、高內聚的設計中,模塊間的相互作用很小,而且十分小心地詳盡地說明了接口,那么接口錯誤將可保持在最低限度。
以下面程序結構圖說明非漸增式集成方法過程:
圖1 程序結構圖
非漸增式以下列方式進行:首先對六個模塊中的每一個執(zhí)行單元測試,對單元的測試次序可以順序地進行或平行地進行。最后把單元組合或結合成一個程序。根據單元在結構圖的地位,對模塊M2配備了驅動模塊D1和樁模塊S1,對模塊M4配備了驅動模塊D3和樁模塊S2,對模塊M3、M5、M6只配備了驅動模塊D2、D4、D5,對主模塊M1,配備了樁模塊S3、S4、S5。分別進行單元測試后,按結構圖1形式聯接起來,進行集成測試。
圖2 非漸增式集成測試
漸增式測試不是單獨地測試每個單元,而是首先把下一個要被測試的單元同已測試的單元集合組合起來,然后再測試。典型的分為自頂向下、自底向上和三明治集成3種。
1.2.1 自頂向下集成
自頂向下集成測試從主程序開始。被主程序調用的下層單元都作為樁函數出現,樁就是模擬被調用單元的一次性代碼[4]。把附屬主控模塊的子模塊孫模塊單元等集成起來的方式有深度優(yōu)先和廣度優(yōu)先兩種。
圖3 深度優(yōu)先自頂向下測試
深度優(yōu)先方法是先把結構中的一條主要的控制路徑上的全部模塊完全集成起來。主要路徑的選擇與特定的軟件應用特性有關,可以盡量選取程序主要功能所涉及的路徑。如圖3所示,選擇左側路徑,先集成M1、M2及M5,下一步集成M8,如果M2的某個功能需要也可以先集成M6,然后在聯結中間和右面的路徑。
廣度優(yōu)先方法從結構的頂層開始逐層向下集成。把上一層模塊直接調用的模塊集成進去,然后對每一個新集成進去的模塊再把其直接調用的模塊集成進去。如圖3所示,從M1出發(fā),先集成M2、M3及樁模塊S4,接著是M5、M6這一層,以此類推。
自頂向下的集成過程為以下五個步驟:
1)用主控制模塊做測試驅動模塊,用樁模塊代替所有直接被主控模塊調用的模塊。
2)根據所選擇的集成方法(深度優(yōu)先或廣度優(yōu)先)以及新模塊的選擇原則,每次用一個實際單元替代一個被調用的樁模塊,并開發(fā)該單元可能需要的樁模塊。
3)每組裝一個新模塊,測試一個。
4)完成一組測試后,用實際模塊替換另一個樁模塊;并為該實際模塊開發(fā)必要的樁模塊。
5)為了避免引入新的錯誤,再次復用以前使用過的測試用例進行測試,即重復以前執(zhí)行過的部分或全部測試。
1.2.2 自底向上集成
自底向上集成測試是按照自頂向下順序的鏡像,不同的是,樁模塊由模擬功能分解樹上一層單元的驅動模塊代替。在自底向上集成測試過程中,首先從分解樹的葉開始,并用編寫的驅動測試[5]。驅動模塊單元中的一次性代碼比樁模塊單元中的少。大多數系統在接近葉時都有較高的扇出數,因此在自底向上集成測試過程中,不需要同樣數量的驅動模塊單元,不過代價是驅動模塊單元比較復雜。
過程如圖4所示,D1、D2、D3、D4是模塊集合1、2、3、4的驅動模塊,集合1、2、3上屬于M2,去掉D1、D2、D3將這3個集合直接與M2接口;同樣地,在集合4與M3接口前去掉D4,M2與M3最后與M1接口。
圖4 自底向上測試示意圖
自底向上集成過程可用以下步驟實現:
1)把底層模塊組裝成實現特定軟件子功能的集合。
2)為每個集合設計一個驅動模塊單元,作為測試控制程序,明確測試用例的輸入和輸出。
3)對模塊集合進行測試。
4)按結構自底向上的順序,用真實模塊替換驅動模塊,將模塊集合組裝起來形成新的模塊,再進行測試,直到全部完成。
1.2.3 三明治集成
三明治集成測試是自頂向下和自底向上兩種集成測試的組合。如果通過分解樹考慮三明治集成測試,則只需要在子樹上進行大爆炸集成[6]。樁模塊單元和驅動器模塊單元的開發(fā)工作都比較小,不過作為大爆炸集成的后果,在一定程度上增加了定位缺陷的困難。對于有多個關鍵模塊,從兩頭開始向中間進行,關鍵模塊單元選用自底向上集成測試方法,需要考慮編寫測試驅動模塊和測試樁模塊的工作量[7]。
除了大爆炸集成測試,基于分解的方法在直覺上很清楚,使用通過測試的組件構建。發(fā)現失效后,就可以懷疑最新加入的單元模塊。集成測試方法很容易根據分解樹追蹤[8]。整個機制是根據結構集成單元模塊,假設正確行為來自個體正確的單元模塊和正確的接口。給定分解樹所需集成測試會話數的計算公式如下:
會話=節(jié)點-頁+邊
(1)
對于自頂向下集成方法,需要開發(fā)(節(jié)點-1個)樁模塊;對于自底向上集成方法,需要開發(fā)(節(jié)點-葉子)驅動器模塊[9]。
單個模塊分別都可以單獨運行,可是這些模塊集成在一起就不能正常工作,主要原因是因為這些模塊在相互集成時接口間會引入新的問題。部分數據經過接口很可能丟棄;這個模塊單元對那個模塊單元可能造成不正常影響;幾個子功能相互組合起來不能完成主要的功能;誤差經過不斷積累達到難以接受的程度;全局數據類型定義出現了數據覆蓋之類的錯誤等。集成測試的目的是盡可能暴露單元測試時難以暴露的結構性錯誤。問題定位究竟是這個模塊是否破壞了哪個模塊的功能,或者是部分數據通過接口時是否丟失,或者是子功能組合起來難以實現主要功能,或者是誤差是否進行反復多次積累等。集成測試按設計要求把通過的各個單元測試的模塊集成在一起進行測試,以便發(fā)現與內部接口相關聯的各種錯誤。
進行集成測試需要確定關鍵單元模塊,對這些關鍵單元模塊進行集成測試。關鍵單元模塊應具有以下特征之一:1)滿足軟件功能需求;2)有清晰明確定義的指標要求;3)具備控制決策功能;4)較復雜、較容易產生錯誤的模塊;
集成測試時需要考慮如下要素:1)使用哪一種集成測試方法來進行;2)是否需要特別的軟硬件設備和環(huán)境在測試過程中;3)各個單元模塊集成測試的順序;4)集成測試的順序是否與模塊代碼的設計編寫進度一致;
進行集成測試需要使用集成測試用例,進行一次集成測試,就需要生成一系列集成測試用例。測試的重點是設計有效的測試用例。由于完全測試具有不確定性,因此發(fā)現盡可能多的錯誤使用有限的測試用例就顯得非常重要。設計和執(zhí)行測試用例需要遵守下面幾個重要原則:
1)設計測試用例要明確輸入數據應同時明確程序的預期輸出;2)設計測試用例應該系統地科學地進行,不能隨便設計;3)測試用例輸入需要包含不合理的數據和合理的數據;4)不僅要檢查程序是否做了不應該做的事情,而且還要檢查程序是否做了該做的事情;5)記錄合理的測試用例,為了以后復用;
非增量式集成測試的弊端是對每個錯誤的定位和糾正特別困難。一次集成可能發(fā)現一大堆錯誤,有可能在改正一個錯誤的同時引入另一個錯誤,新舊錯誤混雜,容易出現混亂。定位出錯的原因和位置更加困難。
自頂向下集成的弊端是需要建立樁模塊。使樁模塊模擬實際子單元模塊的功能有些困難,因為樁模塊在接收了所測模塊發(fā)送的指令后需要按照它所代替的實際子模塊返回相應的值,這加強建立樁模塊的難度,導致增添額外的樁模塊測試。并且輸入/輸出單元模塊和較復雜算法大都在底層,這是很容易有問題的模塊單元,一旦有這些問題,將導致無數次回歸測試。而自頂向下集成測試方法的好處是能比較早地對發(fā)現問題。選用采用深度優(yōu)先自頂向下集成或是廣度優(yōu)先自頂向下集成,是根據軟件部件的特點進行決定。深度優(yōu)先自頂向下集成是把主控制路徑上的模塊單元集成在一起,選擇哪一條路徑作為主控制路徑一般根據問題的特性確定。廣度優(yōu)先自頂向下集成方法是沿控制層次結構水平地向下移動。
自底向上集成方法的弊端是直到最后一個模塊加上去后程序才形成一個實體。作為一個實體存在程序一直不能,在自底向上集成和測試的過程中,最后才能接觸到對主要部分的控制。這種方式的好處是不需要建立樁模塊,需要建立驅動模塊單元,相對來說建立驅動模塊單元一般比建立樁模塊單元容易,由于涉及到輸入/輸出的模塊單元和較復雜算法是最先進行集成,這樣能盡早地測試容易出問題的部分。此外自底向上集成測試可以提高測試效率,同時進行多個單元模塊集成測試。
由于航天型號軟件大多有相當部分復雜的科學計算或數據處理,領域應用背景強,不易編寫樁模塊,故而盡量不采用需編寫樁模塊的辦法。因此不采用非漸增式方法集成。航天型號軟件算法復雜,可靠性、安全性要求高,其中故障處理路徑、降級處理路徑、錯誤處理路徑、最長執(zhí)行時間路徑等都是重要的功能、性能關鍵路徑,這些重要特殊的路徑需要高強度仔細的測試,因此控制輸入數據,測試特殊路徑的能力很重要。所以不采用漸增式方法的三明治集成測試方法和自底向上集成測試方法。深度優(yōu)先和廣度優(yōu)先自頂向下集成方法的主要區(qū)別在于組裝次序,根據航天軟件關鍵模塊功能高內聚的特點,采用深度優(yōu)先自頂向下集成方法,不采用廣度優(yōu)先自頂向下集成方法。
根據航天型號極特殊的運行環(huán)境和特點,基于VC33航天型號軟件選擇采用深度優(yōu)先自頂向下集成測試方法。以通訊控制軟件初始化功能為例,應用該方法如下。
1)根據該軟件設計,通訊控制軟件劃初始化功能主要由4個部件process、inithard、selftest、initvar組成,其中inithard部件由start_timer、delay_us、init_Gpio、initXint、setTimer、aceInitBRT、initTimer、InitTable、initFlash、memCopy、aceSetmode、acewait、acesetTllcmd、acegetRTaddr、aceCtrl_WD、acesoftReset、initBRT、aceGetSubadd共18個函數組成。初始化模塊劃分圖如下:
圖5 軟件模塊劃分圖
2)使用測試工具Testbed進行分解集成部件,SCU-CSC-init部件采用深度優(yōu)先“自頂向下”的集成測試方法,由于SCU-CSC-init部件調用關系比較復雜,采用按分支添加函數進行集成測試,當被調用函數有多個上層調用函數時,分別考慮單元接口調用情況,從而達到遍歷的目的,對尚未添加函數人為進行插樁處理,從而明確函數調用關系,同時根據函數的正常情況和異常情況并考慮邊界情況進行綜合設計用例。通訊控制軟件初始化模塊路徑流程圖如圖6所示。
圖6 路徑流程圖
3)在函數InitHard調用函數MemCopy時,選擇基于路徑測試方法查看語句覆蓋率的覆蓋情況,語句覆蓋率S未達到100%,如果出現未覆蓋的函數MemCopy(struct IMU_Static_Model *ps_IMU_Static_M_i,struct Sum_Model _IMU_Diagnose *ps_sum_M),分析沒有完全覆蓋的原因是因為部分指向寄存器地址的指針使用引起,不存在軟件缺陷。通訊控制軟件初始化模塊過程基于路徑語句覆蓋率如圖7所示。
圖7 基于路徑語句覆蓋率
根據航天型號極特殊的運行環(huán)境和特點,基于VC33航天型號軟件選擇采用深度優(yōu)先自頂向下集成測試方法。以指導工程測試人員針對高可靠性航天軟件進行測試方法的選擇。由實驗結果可知,航天軟件集成測試采用深度優(yōu)先自頂向下集成測試方法,可以準確地反映出被測軟件存在于單元間接口的諸多問題,使得整個軟件得到多層次的測試,反映出軟件可靠和缺陷的關系。通過實踐驗證該方法的可行性與有效性。同時,從新一代運載火箭飛行控制軟件實驗的分析結果也可以看出,利用本文方法選取的新一代運載火箭飛行控制軟件測試方法進行集成測試,能夠得到比較滿意的系統高可靠性和質量保證。