1. 軟件測(cè)試基礎(chǔ)1.1. 什么是軟件測(cè)試軟件測(cè)試是為了發(fā)現(xiàn)錯(cuò)誤而執(zhí)行程序的過程?;蛘哒f,軟件測(cè)試是根據(jù)軟件開發(fā)各階段的規(guī)格說明和程序的內(nèi)部結(jié)構(gòu)而精心設(shè)計(jì)一批測(cè)試用例(即輸入數(shù)據(jù)及其預(yù)期的輸出結(jié)果),并利用這些測(cè)試用例去運(yùn)行程序,以發(fā)現(xiàn)程序錯(cuò)誤的過程。 軟件測(cè)試在軟件生存期中橫跨兩個(gè)階段:通常在編寫出每一個(gè)模塊之后就對(duì)它做必要的測(cè)試(稱為單元測(cè)試)。模塊的編寫者與測(cè)試者是同一個(gè)人。編碼與單元測(cè)試屬于軟件生存期中的同一個(gè)階段。在這個(gè)階段結(jié)束之后,對(duì)軟件系統(tǒng)還要進(jìn)行各種綜合測(cè)試,這是軟件生存期的另一個(gè)獨(dú)立的階段,即測(cè)試階段,通常由專門的測(cè)試人員承擔(dān)這項(xiàng)工作。
1.2. 軟件測(cè)試的目的、任務(wù)和原則設(shè)計(jì)測(cè)試的目標(biāo)是想以最少的時(shí)間和人力系統(tǒng)地找出軟件中潛在的各種錯(cuò)誤和缺陷。 軟件測(cè)試的目的,第一是確認(rèn)軟件的質(zhì)量,其一方面是確認(rèn)軟件做了你所期望的事情(Do the right thing),另一方面是確認(rèn)軟件以正確的方式來做了這個(gè)事件(Do it right)。第二是提供信息,比如提供給開發(fā)人員或程序經(jīng)理的回饋信息,為風(fēng)險(xiǎn)評(píng)估所準(zhǔn)備的信息。第三軟件測(cè)試不僅是在測(cè)試軟件產(chǎn)品的本身,而且還包括軟件開發(fā)的過程。如果一個(gè)軟件產(chǎn)品開發(fā)完成之后發(fā)現(xiàn)了很多問題,這說明此軟件開發(fā)過程很可能是有缺陷的。因此軟件測(cè)試的第三個(gè)目的是保證整個(gè)軟件開發(fā)過程是高質(zhì)量的。 測(cè)試人員在軟件開發(fā)過程中的任務(wù): 1、尋找Bug; 2、避免軟件開發(fā)過程中的缺陷; 3、衡量軟件的質(zhì)量; 4、關(guān)注用戶的需求。 軟件測(cè)試的原則: ① 應(yīng)當(dāng)把“盡早地和不斷地進(jìn)行軟件測(cè)試”作為軟件開發(fā)者的座右銘。 不應(yīng)把軟件測(cè)試僅僅看作是軟件開發(fā)的一個(gè)獨(dú)立階段,而應(yīng)當(dāng)把它貫穿到軟件開發(fā)的各個(gè)階段中。堅(jiān)持在軟件開發(fā)的各個(gè)階段的技術(shù)評(píng)審,這樣才能在開發(fā)過程中盡早發(fā)現(xiàn)和預(yù)防錯(cuò)誤,把出現(xiàn)的錯(cuò)誤克服在早期,杜絕某些發(fā)生錯(cuò)誤的隱患。 ② 測(cè)試用例應(yīng)由測(cè)試輸入數(shù)據(jù)和與之對(duì)應(yīng)的預(yù)期輸出結(jié)果這兩部分組成。 測(cè)試以前應(yīng)當(dāng)根據(jù)測(cè)試的要求選擇測(cè)試用例(Test case),用來檢驗(yàn)程序員編制的程序,因此不但需要測(cè)試的輸入數(shù)據(jù),而且需要針對(duì)這些輸入數(shù)據(jù)的預(yù)期輸出結(jié)果。 ③ 程序員應(yīng)避免檢查自己的程序。 程序員應(yīng)盡可能避免測(cè)試自己編寫的程序,程序開發(fā)小組也應(yīng)盡可能避免測(cè)試本小組開發(fā)的程序。如果條件允許,最好建立獨(dú)立的軟件測(cè)試小組或測(cè)試機(jī)構(gòu)。這點(diǎn)不能與程序的調(diào)試(debuging)相混淆。調(diào)試由程序員自己來做可能更有效。 ④ 在設(shè)計(jì)測(cè)試用例時(shí),應(yīng)當(dāng)包括合理的輸入條件和不合理的輸入條件。 合理的輸入條件是指能驗(yàn)證程序正確的輸入條件,不合理的輸入條件是指異常的,臨界的,可能引起問題異變的輸入條件。軟件系統(tǒng)處理非法命令的能力必須在測(cè)試時(shí)受到檢驗(yàn)。用不合理的輸入條件測(cè)試程序時(shí),往往比用合理的輸入條件進(jìn)行測(cè)試能發(fā)現(xiàn)更多的錯(cuò)誤。 ⑤ 充分注意測(cè)試中的群集現(xiàn)象。 在被測(cè)程序段中,若發(fā)現(xiàn)錯(cuò)誤數(shù)目多,則殘存錯(cuò)誤數(shù)目也比較多。這種錯(cuò)誤群集性現(xiàn)象,已為許多程序的測(cè)試實(shí)踐所證實(shí)。根據(jù)這個(gè)規(guī)律,應(yīng)當(dāng)對(duì)錯(cuò)誤群集的程序段進(jìn)行重點(diǎn)測(cè)試,以提高測(cè)試投資的效益。 ⑥ 嚴(yán)格執(zhí)行測(cè)試計(jì)劃,排除測(cè)試的隨意性。 測(cè)試之前應(yīng)仔細(xì)考慮測(cè)試的項(xiàng)目,對(duì)每一項(xiàng)測(cè)試做出周密的計(jì)劃,包括被測(cè)程序的功能、輸入和輸出、測(cè)試內(nèi)容、進(jìn)度安排、資源要求、測(cè)試用例的選擇、測(cè)試的控制方式和過程等,還要包括系統(tǒng)的組裝方式、跟蹤規(guī)程、調(diào)試規(guī)程,回歸測(cè)試的規(guī)定,以及評(píng)價(jià)標(biāo)準(zhǔn)等。對(duì)于測(cè)試計(jì)劃,要明確規(guī)定,不要隨意解釋。 ⑦ 應(yīng)當(dāng)對(duì)每一個(gè)測(cè)試結(jié)果做全面檢查。 有些錯(cuò)誤的征兆在輸出實(shí)測(cè)結(jié)果時(shí)已經(jīng)明顯地出現(xiàn)了,但是如果不仔細(xì)地全面地檢查測(cè)試結(jié)果,就會(huì)使這些錯(cuò)誤被遺漏掉。所以必須對(duì)預(yù)期的輸出結(jié)果明確定義,對(duì)實(shí)測(cè)的結(jié)果仔細(xì)分析檢查,抓住征侯,暴露錯(cuò)誤。 ⑧ 妥善保存測(cè)試計(jì)劃,測(cè)試用例,出錯(cuò)統(tǒng)計(jì)和最終分析報(bào)告,為維護(hù)提供方便。
1.3. 確認(rèn)和驗(yàn)證的關(guān)系確認(rèn)(Validation)是一系列的活動(dòng)和過程,其目的是想證實(shí)在一個(gè)給定的外部環(huán)境中軟件的邏輯正確性。它包括需求規(guī)格說明的確認(rèn)和程序的確認(rèn),而程序的確認(rèn)又分為靜態(tài)確認(rèn)與動(dòng)態(tài)確認(rèn)。靜態(tài)確認(rèn)一般不在計(jì)算機(jī)上實(shí)際執(zhí)行程序,而是通過人工分析或者程序正確性證明來確認(rèn)程序的正確性; 動(dòng)態(tài)確認(rèn)主要通過動(dòng)態(tài)分析和程序測(cè)試來檢查程序的執(zhí)行狀態(tài),以確認(rèn)程序是否有問題。 驗(yàn)證(Verification),則試圖證明在軟件生存期各個(gè)階段,以及階段間的邏輯協(xié)調(diào)性、完備性和正確性。 確認(rèn)與驗(yàn)證工作都屬于軟件測(cè)試。在對(duì)需求理解與表達(dá)的正確性、設(shè)計(jì)與表達(dá)的正確性、實(shí)現(xiàn)的正確性以及運(yùn)行的正確性的驗(yàn)證中,任何一個(gè)環(huán)節(jié)上發(fā)生了問題都可能在軟件測(cè)試中表現(xiàn)出來。
1.4. 測(cè)試信息流測(cè)試信息流如圖1所示。測(cè)試過程需要三類輸入: § 軟件配置:包括軟件需求規(guī)格說明、軟件設(shè)計(jì)規(guī)格說明、源代碼等; § 測(cè)試配置:包括測(cè)試計(jì)劃、測(cè)試用例、測(cè)試驅(qū)動(dòng)程序等; § 測(cè)試工具:測(cè)試工具為測(cè)試的實(shí)施提供某種服務(wù)。例如,測(cè)試數(shù)據(jù)自動(dòng)生成程序、靜態(tài)分析程序、動(dòng)態(tài)分析程序、測(cè)試結(jié)果分析程序、以及驅(qū)動(dòng)測(cè)試的工作臺(tái)等。 測(cè)試之后,用實(shí)測(cè)結(jié)果與預(yù)期結(jié)果進(jìn)行比較。如果發(fā)現(xiàn)出錯(cuò)的數(shù)據(jù),就要進(jìn)行調(diào)試。對(duì)已經(jīng)發(fā)現(xiàn)的錯(cuò)誤進(jìn)行錯(cuò)誤定位和確定出錯(cuò)性質(zhì),并改正這些錯(cuò)誤,同時(shí)修改相關(guān)的文檔。修正后的文檔一般都要經(jīng)過再次測(cè)試,直到通過測(cè)試為止。 通過收集和分析測(cè)試結(jié)果數(shù)據(jù),對(duì)軟件建立可靠性模型。 圖1 測(cè)試信息流
如果測(cè)試發(fā)現(xiàn)不了錯(cuò)誤,那么可以肯定,測(cè)試配置考慮得不夠細(xì)致充分,錯(cuò)誤仍然潛伏在軟件中。這些錯(cuò)誤最終不得不由用戶在使用中發(fā)現(xiàn),并在維護(hù)時(shí)由開發(fā)者去改正。但那時(shí)改正錯(cuò)誤的費(fèi)用將比在開發(fā)階段改正錯(cuò)誤的費(fèi)用要高出40倍到60倍。
1.5. 測(cè)試與軟件開發(fā)各階段的關(guān)系軟件開發(fā)過程是一個(gè)自頂向下,逐步細(xì)化的過程,而測(cè)試過程則是依相反的順序安排的 自底向上,逐步集成的過程。低一級(jí)測(cè)試為上一級(jí)測(cè)試準(zhǔn)備條件。參看圖1.2,首先對(duì)每一個(gè)程序模塊進(jìn)行單元測(cè)試,消除程序模塊內(nèi)部在邏輯上和功能上的錯(cuò)誤和缺陷。再對(duì)照軟件設(shè)計(jì)進(jìn)行集成測(cè)試,檢測(cè)和排除子系統(tǒng)(或系統(tǒng))結(jié)構(gòu)上的錯(cuò)誤。隨后再對(duì)照需求,進(jìn)行確認(rèn)測(cè)試。最后從系統(tǒng)全體出發(fā),運(yùn)行系統(tǒng),看是否滿足要求。
圖2 軟件測(cè)試與軟件開發(fā)過程的關(guān)系
2. 程序錯(cuò)誤分類由于人們對(duì)錯(cuò)誤有不同的理解和認(rèn)識(shí),所以目前還沒有一個(gè)統(tǒng)一的錯(cuò)誤分類方法。錯(cuò)誤難于分類的原因,一方面是由于一個(gè)錯(cuò)誤有許多征兆,因而它可以被歸入不同的類。另一方面是因?yàn)榘岩粋€(gè)給定的錯(cuò)誤歸于哪一類,還與錯(cuò)誤的來源和程序員的心理狀態(tài)有關(guān)。 2.1 按錯(cuò)誤的影響和后果分類§ 較小錯(cuò)誤:只對(duì)系統(tǒng)輸出有一些非實(shí)質(zhì)性影響。如,輸出的數(shù)據(jù)格式不合要求等。 § 中等錯(cuò)誤:對(duì)系統(tǒng)的運(yùn)行有局部影響。如輸出的某些數(shù)據(jù)有錯(cuò)誤或出現(xiàn)冗余。 § 較嚴(yán)重錯(cuò)誤:系統(tǒng)的行為因錯(cuò)誤的干擾而出現(xiàn)明顯不合情理的現(xiàn)象。比如開出了0.00元的支票,系統(tǒng)的輸出完全不可信賴。 § 嚴(yán)重錯(cuò)誤:系統(tǒng)運(yùn)行不可跟蹤,一時(shí)不能掌握其規(guī)律,時(shí)好時(shí)壞。 § 非常嚴(yán)重的錯(cuò)誤:系統(tǒng)運(yùn)行中突然停機(jī),其原因不明,無法軟啟動(dòng)。 § 最嚴(yán)重的錯(cuò)誤:系統(tǒng)運(yùn)行導(dǎo)致環(huán)境破壞,或是造成事故,引起生命、財(cái)產(chǎn)的損失。 2.2 按錯(cuò)誤的性質(zhì)和范圍分類① 功能錯(cuò)誤 § 規(guī)格說明錯(cuò)誤:規(guī)格說明可能不完全,有二義性或自身矛盾。 § 功能錯(cuò)誤:程序?qū)崿F(xiàn)的功能與用戶要求的不一致。這常常是由于規(guī)格說明中包含錯(cuò)誤的功能、多余的功能或遺漏的功能所致。 § 測(cè)試錯(cuò)誤:軟件測(cè)試的設(shè)計(jì)與實(shí)施發(fā)生錯(cuò)誤。軟件測(cè)試自身也可能發(fā)生錯(cuò)誤。 § 測(cè)試標(biāo)準(zhǔn)引起的錯(cuò)誤:對(duì)軟件測(cè)試的標(biāo)準(zhǔn)要選擇適當(dāng),若測(cè)試標(biāo)準(zhǔn)太復(fù)雜,則導(dǎo)致測(cè)試過程出錯(cuò)的可能就大。 ② 系統(tǒng)錯(cuò)誤 § 外部接口錯(cuò)誤:外部接口指如終端、打印機(jī)、通信線路等系統(tǒng)與外部環(huán)境通信的手段。所有外部接口之間,人與機(jī)器之間的通信都使用形式的或非形式的專門協(xié)議。如果協(xié)議有錯(cuò),或太復(fù)雜,難以理解,致使在使用中出錯(cuò)。此外還包括對(duì)輸入/輸出格式錯(cuò)誤理解,對(duì)輸入數(shù)據(jù)不合理的容錯(cuò)等等。 § 內(nèi)部接口錯(cuò)誤:內(nèi)部接口指程序之間的聯(lián)系。它所發(fā)生的錯(cuò)誤與程序內(nèi)實(shí)現(xiàn)的細(xì)節(jié)有關(guān)。例如,設(shè)計(jì)協(xié)議錯(cuò)、輸入/輸出格式錯(cuò)、數(shù)據(jù)保護(hù)不可靠、子程序訪問錯(cuò)等。 § 硬件結(jié)構(gòu)錯(cuò)誤:這類錯(cuò)誤在于不能正確地理解硬件如何工作。例如,忽視或錯(cuò)誤地理解分頁機(jī)構(gòu)、位址生成、信道容量、I/O指令、中斷處理、設(shè)備初始化和啟動(dòng)等而導(dǎo)致的出錯(cuò)。 § 操作系統(tǒng)錯(cuò)誤:這類錯(cuò)誤主要是由于不了解操作系統(tǒng)的工作機(jī)制而導(dǎo)致出錯(cuò)。當(dāng)然,操作系統(tǒng)本身也有錯(cuò)誤,但是一般用戶很難發(fā)現(xiàn)這種錯(cuò)誤。 § 軟件結(jié)構(gòu)錯(cuò)誤:由于軟件結(jié)構(gòu)不合理或不清晰而引起的錯(cuò)誤。這種錯(cuò)誤通常與系統(tǒng)的負(fù)載有關(guān),而且往往在系統(tǒng)滿載時(shí)才出現(xiàn)。這是最難發(fā)現(xiàn)的一類錯(cuò)誤。例如,錯(cuò)誤地設(shè)置局部參數(shù)或全局參數(shù);錯(cuò)誤地假定寄存器與內(nèi)存單元初始化了;錯(cuò)誤地假定不會(huì)發(fā)生中斷而導(dǎo)致不能封鎖或開中斷;錯(cuò)誤地假定程序可以繞過數(shù)據(jù)的內(nèi)部鎖而導(dǎo)致不能關(guān)閉或打開內(nèi)部鎖;錯(cuò)誤地假定被調(diào)用子程序常駐內(nèi)存或非常駐內(nèi)存等等,都將導(dǎo)致軟件出錯(cuò)。 § 控制與順序錯(cuò)誤:這類錯(cuò)誤包括:忽視了時(shí)間因素而破壞了事件的順序;猜測(cè)事件出現(xiàn)在指定的序列中;等待一個(gè)不可能發(fā)生的條件;漏掉先決條件;規(guī)定錯(cuò)誤的優(yōu)先級(jí)或程序狀態(tài);漏掉處理步驟;存在不正確的處理步驟或多余的處理步驟等。 § 資源管理錯(cuò)誤:這類錯(cuò)誤是由于不正確地使用資源而產(chǎn)生的。例如,使用未經(jīng)獲準(zhǔn)的資源;使用后未釋放資源;資源死鎖;把資源鏈接在錯(cuò)誤的序列中等等。 ③ 加工錯(cuò)誤 § 算術(shù)與操作錯(cuò)誤:指在算術(shù)運(yùn)算、函數(shù)求值和一般操作過程中發(fā)生的錯(cuò)誤。包括:數(shù)據(jù)類型轉(zhuǎn)換錯(cuò);除法溢出;錯(cuò)誤地使用關(guān)系比較符;用整數(shù)與浮點(diǎn)數(shù)做比較等。 § 初始化錯(cuò)誤:典型的錯(cuò)誤有:忘記初始化工作區(qū),忘記初始化寄存器和資料區(qū);錯(cuò)誤地對(duì)循環(huán)控制變量賦初值;用不正確的格式,數(shù)據(jù)或類型進(jìn)行初始化等等。 § 控制和次序錯(cuò)誤:這類錯(cuò)誤與系統(tǒng)級(jí)同名錯(cuò)誤類似,但它是局部錯(cuò)誤。包括:遺漏路徑;不可達(dá)到的代碼;不符合語法的循環(huán)嵌套;循環(huán)返回和終止的條件不正確;漏掉處理步驟或處理步驟有錯(cuò)等。 § 靜態(tài)邏輯錯(cuò)誤:這類錯(cuò)誤主要包括:不正確地使用CASE語句;在表達(dá)式中使用不正確的否定(例如用“>”代替“<”的否定);對(duì)情況不適當(dāng)?shù)胤纸馀c組合;混淆“或”與“異或”等。 ④ 數(shù)據(jù)錯(cuò)誤 § 動(dòng)態(tài)數(shù)據(jù)錯(cuò)誤:動(dòng)態(tài)數(shù)據(jù)是在程序執(zhí)行過程中暫時(shí)存在的數(shù)據(jù)。各種不同類型的動(dòng)態(tài)數(shù)據(jù)在程序執(zhí)行期間將共享一個(gè)共同的存儲(chǔ)區(qū)域,若程序啟動(dòng)時(shí)對(duì)這個(gè)區(qū)域未初始化,就會(huì)導(dǎo)致數(shù)據(jù)出錯(cuò)。由于動(dòng)態(tài)數(shù)據(jù)被破壞的位置可能與出錯(cuò)的位置在距離上相差很遠(yuǎn),因此要發(fā)現(xiàn)這類錯(cuò)誤比較困難。 § 靜態(tài)數(shù)據(jù)錯(cuò)誤:靜態(tài)數(shù)據(jù)在內(nèi)容和格式上都是固定的。它們直接或間接地出現(xiàn)在程序或數(shù)據(jù)庫中。由編譯程序或其它專門程序?qū)λ鼈冏鲱A(yù)處理。這是在程序執(zhí)行前防止靜態(tài)錯(cuò)誤的好辦法,但預(yù)處理也會(huì)出錯(cuò)。 § 數(shù)據(jù)內(nèi)容錯(cuò)誤:數(shù)據(jù)內(nèi)容是指存儲(chǔ)于存儲(chǔ)單元或數(shù)據(jù)結(jié)構(gòu)中的位串、字符串或數(shù)字。數(shù)據(jù)內(nèi)容本身沒有特定的含義,除非通過硬件或軟件給予解釋。數(shù)據(jù)內(nèi)容錯(cuò)誤就是由于內(nèi)容被破壞或被錯(cuò)誤地解釋而造成的錯(cuò)誤。 § 數(shù)據(jù)結(jié)構(gòu)錯(cuò)誤:數(shù)據(jù)結(jié)構(gòu)是指數(shù)據(jù)元素的大小和組織形式。在同一存儲(chǔ)區(qū)域中可以定義不同的數(shù)據(jù)結(jié)構(gòu)。數(shù)據(jù)結(jié)構(gòu)錯(cuò)誤主要包括結(jié)構(gòu)說明錯(cuò)誤及把一個(gè)數(shù)據(jù)結(jié)構(gòu)誤當(dāng)做另一類數(shù)據(jù)結(jié)構(gòu)使用的錯(cuò)誤。這是更危險(xiǎn)的錯(cuò)誤。 § 數(shù)據(jù)屬性錯(cuò)誤:數(shù)據(jù)屬性是指數(shù)據(jù)內(nèi)容的含義或語義。例如,整數(shù)、字符串、子程序等等。數(shù)據(jù)屬性錯(cuò)誤主要包括:對(duì)數(shù)據(jù)屬性不正確地解釋,比如錯(cuò)把整數(shù)當(dāng)實(shí)數(shù),允許不同類型數(shù)據(jù)混合運(yùn)算而導(dǎo)致的錯(cuò)誤等。 ⑤ 代碼錯(cuò)誤 主要包括:語法錯(cuò)誤;打字錯(cuò)誤;對(duì)語句或指令不正確理解所產(chǎn)生的錯(cuò)誤。 2.3按軟件生存期階段分類Good enough-Gerhart分類方法把軟件的邏輯錯(cuò)誤按生存期不同階段分為4類。 ① 問題定義(需求分析)錯(cuò)誤 它們是在軟件定義階段,分析員研究用戶的要求后所編寫的文檔中出現(xiàn)的錯(cuò)誤。換句話說,這類錯(cuò)誤是由于問題定義不滿足用戶的要求而導(dǎo)致的錯(cuò)誤。 ② 規(guī)格說明錯(cuò)誤 這類錯(cuò)誤是指規(guī)格說明與問題定義不一致所產(chǎn)生的錯(cuò)誤。它們又可以細(xì)分成: § 不一致性錯(cuò)誤:規(guī)格說明中功能說明與問題定義發(fā)生矛盾。 § 冗余性錯(cuò)誤:規(guī)格說明中某些功能說明與問題定義相比是多余的。 § 不完整性錯(cuò)誤:規(guī)格說明中缺少某些必要的功能說明。 § 不可行錯(cuò)誤:規(guī)格說明中有些功能要求是不可行的。 § 不可測(cè)試錯(cuò)誤:有些功能的測(cè)試要求是不現(xiàn)實(shí)的。 3設(shè)計(jì)錯(cuò)誤 這是在設(shè)計(jì)階段產(chǎn)生的錯(cuò)誤,它使系統(tǒng)的設(shè)計(jì)與需求規(guī)格說明中的功能說明不相符。它們又可以細(xì)分為: § 設(shè)計(jì)不完全錯(cuò)誤:某些功能沒有被設(shè)計(jì),或設(shè)計(jì)得不完全。 § 算法錯(cuò)誤:算法選擇不合適。主要表現(xiàn)為算法的基本功能不滿足功能要求、算法不可行或者算法的效率不符合要求。 § 模塊接口錯(cuò)誤:模塊結(jié)構(gòu)不合理;模塊與外部數(shù)據(jù)庫的接口不一致,模塊之間的接口不一致。 § 控制邏輯錯(cuò)誤:控制流程與規(guī)格說明不一致;控制結(jié)構(gòu)不合理。 § 數(shù)據(jù)結(jié)構(gòu)錯(cuò)誤:數(shù)據(jù)設(shè)計(jì)不合理;與算法不匹配;數(shù)據(jù)結(jié)構(gòu)不滿足規(guī)格說明要求。 ④ 編碼錯(cuò)誤 編碼過程中的錯(cuò)誤是多種多樣的,大體可歸為以下幾種:數(shù)據(jù)說明錯(cuò)、數(shù)據(jù)使用錯(cuò)、計(jì)算錯(cuò)、比較錯(cuò)、控制流錯(cuò)、接口錯(cuò)、輸入/輸出錯(cuò),及其它的錯(cuò)誤。 在不同的開發(fā)階段,錯(cuò)誤的類型和表現(xiàn)形式是不同的,故應(yīng)當(dāng)采用不同的方法和策略來進(jìn)行檢測(cè)。 3. 軟件測(cè)試的過程與策略測(cè)試過程按4個(gè)步驟進(jìn)行,即單元測(cè)試、組裝測(cè)試、確認(rèn)測(cè)試和系統(tǒng)測(cè)試。圖2.1顯示出軟件測(cè)試經(jīng)歷的4個(gè)步驟。單元測(cè)試集中對(duì)用源代碼實(shí)現(xiàn)的每一個(gè)程序單元進(jìn)行測(cè)試,檢查各個(gè)程序模塊是否正確地實(shí)現(xiàn)了規(guī)定的功能。然后,進(jìn)行集成測(cè)試,根據(jù)設(shè)計(jì)規(guī)定的軟件體系結(jié)構(gòu),把已測(cè)試過的模塊組裝起來,在組裝過程中,檢查程序結(jié)構(gòu)組裝的正確性。確認(rèn)測(cè)試則是要檢查已實(shí)現(xiàn)的軟件是否滿足了需求規(guī)格說明中確定了的各種需求,以及軟件配置是否完全、正確。最后是系統(tǒng)測(cè)試,把已經(jīng)經(jīng)過確認(rèn)的軟件納入實(shí)際運(yùn)行環(huán)境中,與其它系統(tǒng)成份組合在一起進(jìn)行測(cè)試。嚴(yán)格地說,系統(tǒng)測(cè)試已超出了軟件工程的范圍。
圖3 軟件測(cè)試的過程
3.1單元測(cè)試單元測(cè)試的對(duì)象是軟件設(shè)計(jì)的最小單位——模塊。單元測(cè)試的依據(jù)是詳細(xì)設(shè)計(jì)描述,單元測(cè)試應(yīng)對(duì)模塊內(nèi)所有重要的控制路徑設(shè)計(jì)測(cè)試用例,以便發(fā)現(xiàn)模塊內(nèi)部的錯(cuò)誤。單元測(cè)試多采用白盒測(cè)試技術(shù),系統(tǒng)內(nèi)多個(gè)模塊可以并行地進(jìn)行測(cè)試。 單元測(cè)試任務(wù):
3.2 集成測(cè)試在單元測(cè)試的基礎(chǔ)上,需要將所有模塊按照設(shè)計(jì)要求組裝成為系統(tǒng)。這時(shí)需要考慮: § 在把各個(gè)模塊連接起來的時(shí)侯,穿越模塊接口的數(shù)據(jù)是否會(huì)丟失; § 一個(gè)模塊的功能是否會(huì)對(duì)另一個(gè)模塊的功能產(chǎn)生不利的影響; § 各個(gè)子功能組合起來,能否達(dá)到預(yù)期要求的父功能; § 全局?jǐn)?shù)據(jù)結(jié)構(gòu)是否有問題; § 單個(gè)模塊的誤差累積起來,是否會(huì)放大,從而達(dá)到不能接受的程度。 § 單個(gè)模塊的錯(cuò)誤是否會(huì)導(dǎo)致數(shù)據(jù)庫錯(cuò)誤。 選擇什么方式把模塊組裝起來形成一個(gè)可運(yùn)行的系統(tǒng),直接影響到模塊測(cè)試用例的形式、所用測(cè)試工具的類型、模塊編號(hào)的次序和測(cè)試的次序、以及生成測(cè)試用例的費(fèi)用和調(diào)試的費(fèi)用。通常,把模塊組裝成為系統(tǒng)的方式有兩種方式: ① 一次性集成方式 它是一種非增殖式集成方式。也叫做整體拼裝。使用這種方式,首先對(duì)每個(gè)模塊分別進(jìn)行模塊測(cè)試,然后再把所有模塊組裝在一起進(jìn)行測(cè)試,最終得到要求的軟件系統(tǒng)。 由于程序中不可避免地存在涉及模塊間接口、全局?jǐn)?shù)據(jù)結(jié)構(gòu)等方面的問題,所以一次試運(yùn)行成功的可能性并不很大。 ② 增殖式集成方式 又稱漸增式集成方式。首先對(duì)一個(gè)個(gè)模塊進(jìn)行模塊測(cè)試,然后將這些模塊逐步組裝成較大的系統(tǒng),在組裝的過程中邊連接邊測(cè)試,以發(fā)現(xiàn)連接過程中產(chǎn)生的問題。最后通過增殖逐步組裝成為要求的軟件系統(tǒng)。 § 自頂向下的增殖方式:將模塊按系統(tǒng)程序結(jié)構(gòu),沿控制層次自頂向下進(jìn)行集成。由于這種增殖方式在測(cè)試過程中較早地驗(yàn)證了主要的控制和判斷點(diǎn)。在一個(gè)功能劃分合理的程序結(jié)構(gòu)中,判斷常出現(xiàn)在較高的層次,較早就能遇到。如果主要控制有問題,盡早發(fā)現(xiàn)它能夠減少以后的返工。 § 自底向上的增殖方式:從程序結(jié)構(gòu)的最底層模塊開始組裝和測(cè)試。因?yàn)槟K是自底向上進(jìn)行組裝,對(duì)于一個(gè)給定層次的模塊,它的子模塊(包括子模塊的所有下屬模塊)已經(jīng)組裝并測(cè)試完成,所以不再需要樁模塊。在模塊的測(cè)試過程中需要從子模塊得到的信息可以直接運(yùn)行子模塊得到。 ③ 混合增殖式測(cè)試:自頂向下增殖的方式和自底向上增殖的方式各有優(yōu)缺點(diǎn)。自頂向下增殖方式的缺點(diǎn)是需要建立樁模塊。要使樁模塊能夠模擬實(shí)際子模塊的功能將是十分困難的。同時(shí)涉及復(fù)雜算法和真正輸入/輸出的模塊一般在底層,它們是最容易出問題的模塊,到組裝和測(cè)試的后期才遇到這些模塊,一旦發(fā)現(xiàn)問題,導(dǎo)致過多的回歸測(cè)試。而自頂向下增殖方式的優(yōu)點(diǎn)是能夠較早地發(fā)現(xiàn)在主要控制方面的問題。自底向上增殖方式的缺點(diǎn)是“程序一直未能做為一個(gè)實(shí)體存在,直到最后一個(gè)模塊加上去后才形成一個(gè)實(shí)體”。就是說,在自底向上組裝和測(cè)試的過程中,對(duì)主要的控制直到最后才接觸到。但這種方式的優(yōu)點(diǎn)是不需要樁模塊,而建立驅(qū)動(dòng)模塊一般比建立樁模塊容易,同時(shí)由于涉及到復(fù)雜算法和真正輸入/輸出的模塊最先得到組裝和測(cè)試,可以把最容易出問題的部分在早期解決。此外自底向上增殖的方式可以實(shí)施多個(gè)模塊的并行測(cè)試。 有鑒于此,通常是把以上兩種方式結(jié)合起來進(jìn)行組裝和測(cè)試。 § 衍變的自頂向下的增殖測(cè)試:它的基本思想是強(qiáng)化對(duì)輸入/輸出模塊和引入新算法模塊的測(cè)試,并自底向上組裝成為功能相當(dāng)完整且相對(duì)獨(dú)立的子系統(tǒng),然后由主模塊開始自頂向下進(jìn)行增殖測(cè)試。 § 自底向上-自頂向下的增殖測(cè)試:它首先對(duì)含讀操作的子系統(tǒng)自底向上直至根結(jié)點(diǎn)模塊進(jìn)行組裝和測(cè)試,然后對(duì)含寫操作的子系統(tǒng)做自頂向下的組裝與測(cè)試。 § 回歸測(cè)試:這種方式采取自頂向下的方式測(cè)試被修改的模塊及其子模塊,然后將這一部分視為子系統(tǒng),再自底向上測(cè)試,以檢查該子系統(tǒng)與其上級(jí)模塊的接口是否適配。 3.3確認(rèn)測(cè)試確認(rèn)測(cè)試又稱有效性測(cè)試。它的任務(wù)是驗(yàn)證軟件的有效性,即驗(yàn)證軟件的功能和性能及其它特性是否與用戶的要求一致。在軟件需求規(guī)格說明書描述了全部用戶可見的軟件屬性,其中有一節(jié)叫做有效性準(zhǔn)則,它包含的信息就是軟件確認(rèn)測(cè)試的基礎(chǔ)。 在確認(rèn)測(cè)試階段需要做的工作如圖5.5所示。首先要進(jìn)行有效性測(cè)試以及軟件配置復(fù)審,然后進(jìn)行驗(yàn)收測(cè)試和安裝測(cè)試,在通過了專家鑒定之后,才能成為可交付的軟件。 圖4 確認(rèn)測(cè)試的步驟
① 進(jìn)行有效性測(cè)試(功能測(cè)試) 有效性測(cè)試是在模擬的環(huán)境(可能就是開發(fā)的環(huán)境)下,運(yùn)用黑盒測(cè)試的方法,驗(yàn)證被測(cè)軟件是否滿足需求規(guī)格說明書列出的需求。為此,需要首先制定測(cè)試計(jì)劃,規(guī)定要做測(cè)試的種類。還需要制定一組測(cè)試步驟,描述具體的測(cè)試用例。通過實(shí)施預(yù)定的測(cè)試計(jì)劃和測(cè)試步驟,確定軟件的特性是否與需求相符,確保所有的軟件功能需求都能得到滿足,所有的軟件性能需求都能達(dá)到,所有的文檔都是正確且便于使用。同時(shí),對(duì)其他軟件需求,例如可移植性、兼容性、出錯(cuò)自動(dòng)恢復(fù)、可維護(hù)性等,也都要進(jìn)行測(cè)試,確認(rèn)是否滿足。 ② 軟件配置復(fù)查 軟件配置復(fù)查的目的是保證軟件配置的所有成分都齊全,各方面的質(zhì)量都符合要求,具有維護(hù)階段所必需的細(xì)節(jié),而且已經(jīng)編排好分類的目錄。 除了按合同規(guī)定的內(nèi)容和要求,由人工審查軟件配置之外,在確認(rèn)測(cè)試的過程中,應(yīng)當(dāng)嚴(yán)格遵守用戶手冊(cè)和操作手冊(cè)中規(guī)定的使用步驟,以便檢查這些文文件數(shù)據(jù)的完整性和正確性。必須仔細(xì)記錄發(fā)現(xiàn)的遺漏和錯(cuò)誤,并且適當(dāng)?shù)匮a(bǔ)充和改正。 ③ 驗(yàn)收測(cè)試 在通過了系統(tǒng)的有效性測(cè)試及軟件配置審查之后,就應(yīng)開始系統(tǒng)的驗(yàn)收測(cè)試。驗(yàn)收測(cè)試是以用戶為主的測(cè)試。軟件開發(fā)人員和QA(質(zhì)量保證)人員也應(yīng)參加。由用戶參加設(shè)計(jì)測(cè)試用例,使用用戶接口輸入測(cè)試數(shù)據(jù),并分析測(cè)試的輸出結(jié)果。一般使用生產(chǎn)中的實(shí)際數(shù)據(jù)進(jìn)行測(cè)試。在測(cè)試過程中,除了考慮軟件的功能和性能外,還應(yīng)對(duì)軟件的可移植性、兼容性、可維護(hù)性、錯(cuò)誤的恢復(fù)功能等進(jìn)行確認(rèn)。 ④ α測(cè)試和β測(cè)試 在軟件交付使用之后,用戶將如何實(shí)際使用程序,對(duì)于開發(fā)者來說是無法預(yù)測(cè)的。因?yàn)橛脩粼谑褂眠^程中常常會(huì)發(fā)生對(duì)使用方法的誤解、異常的數(shù)據(jù)組合、以及產(chǎn)生對(duì)某些用戶來說似乎是清晰的但對(duì)另一些用戶來說卻難以理解的輸出等等。 如果軟件是為多個(gè)用戶開發(fā)的產(chǎn)品的時(shí)侯,讓每個(gè)用戶逐個(gè)執(zhí)行正式的驗(yàn)收測(cè)試是不切實(shí)際的。很多軟件產(chǎn)品生產(chǎn)者采用一種稱之為α測(cè)試和β測(cè)試的測(cè)試方法,以發(fā)現(xiàn)可能只有最終用戶才能發(fā)現(xiàn)的錯(cuò)誤。 α測(cè)試是由一個(gè)用戶在開發(fā)環(huán)境下進(jìn)行的測(cè)試,也可以是公司內(nèi)部的用戶在仿真實(shí)際操作環(huán)境下進(jìn)行的測(cè)試。這是在受控制的環(huán)境下進(jìn)行的測(cè)試。α測(cè)試的目的是評(píng)價(jià)軟件產(chǎn)品的FURPS(即功能、可使用性、可靠性、性能和支持)。尤其注重產(chǎn)品的接口和特色。α測(cè)試人員是除開產(chǎn)品開發(fā)人員之外首先見到產(chǎn)品的人,他們提出的功能和修改意見是特別有價(jià)值的。α測(cè)試可以從軟件產(chǎn)品編碼結(jié)束之時(shí)開始,或在模塊(子系統(tǒng))測(cè)試完成之后開始,也可以在確認(rèn)測(cè)試過程中產(chǎn)品達(dá)到一定的穩(wěn)定和可靠程度之后再開始。有關(guān)的手冊(cè)(草稿)等應(yīng)事先準(zhǔn)備好。 β測(cè)試是由軟件的多個(gè)用戶在一個(gè)或多個(gè)用戶的實(shí)際使用環(huán)境下進(jìn)行的測(cè)試。與α測(cè)試不同的是,開發(fā)者通常不在測(cè)試現(xiàn)場(chǎng)。因而,β測(cè)試是在開發(fā)者無法控制的環(huán)境下進(jìn)行的軟件現(xiàn)場(chǎng)應(yīng)用。在β測(cè)試中,由用戶記下遇到的所有問題,包括真實(shí)的以及主觀認(rèn)定的,定期向開發(fā)者報(bào)告,開發(fā)者在綜合用戶的報(bào)告之后,做出修改,最后將軟件產(chǎn)品交付給全體用戶使用。β測(cè)試主要衡量產(chǎn)品的FURPS。著重于產(chǎn)品的支持性,包括文檔、客戶培訓(xùn)和支持產(chǎn)品生產(chǎn)能力。只有當(dāng)α測(cè)試達(dá)到一定的可靠程度時(shí),才能開始β測(cè)試。由于它處在整個(gè)測(cè)試的最后階段,不能指望這時(shí)發(fā)現(xiàn)主要問題。同時(shí),產(chǎn)品的所有手冊(cè)文本也應(yīng)該在此階段完全定稿。由于β測(cè)試的主要目標(biāo)是測(cè)試可支持性,所以β測(cè)試應(yīng)盡可能由主持產(chǎn)品發(fā)行的人員來管理。 3.4系統(tǒng)測(cè)試所謂系統(tǒng)測(cè)試,是將通過確認(rèn)測(cè)試的軟件,作為整個(gè)基于計(jì)算機(jī)系統(tǒng)的一個(gè)元素,與計(jì)算機(jī)硬件、外設(shè)、某些支持軟件、數(shù)據(jù)和人員等其它系統(tǒng)元素結(jié)合在一起,在實(shí)際運(yùn)行(使用)環(huán)境下,對(duì)計(jì)算機(jī)系統(tǒng)進(jìn)行一系列的組裝測(cè)試和確認(rèn)測(cè)試。 系統(tǒng)測(cè)試的目的在于通過與系統(tǒng)的需求定義作比較,發(fā)現(xiàn)軟件與系統(tǒng)定義不符合或與之矛盾的地方。系統(tǒng)測(cè)試的測(cè)試用例應(yīng)根據(jù)需求分析規(guī)格說明來設(shè)計(jì),并在實(shí)際使用環(huán)境下來運(yùn)行。 4. 測(cè)試用例設(shè)計(jì)4.1測(cè)試方法概述① 黑盒測(cè)試 根據(jù)軟件產(chǎn)品的功能設(shè)計(jì)規(guī)格,在計(jì)算機(jī)上進(jìn)行測(cè)試,以證實(shí)每個(gè)實(shí)現(xiàn)了的功能是否符合要求。這種測(cè)試方法就是黑盒測(cè)試。黑盒測(cè)試意味著測(cè)試要在軟件的接口處進(jìn)行。就是說,這種方法是把測(cè)試對(duì)象看做一個(gè)黑盒子,測(cè)試人員完全不考慮程序內(nèi)部的邏輯結(jié)構(gòu)和內(nèi)部特性,只依據(jù)程序的需求分析規(guī)格說明,檢查程序的功能是否符合它的功能說明。 用黑盒測(cè)試發(fā)現(xiàn)程序中的錯(cuò)誤,必須在所有可能的輸入條件和輸出條件中確定測(cè)試數(shù)據(jù),來檢查程序是否都能產(chǎn)生正確的輸出。 ② 白盒測(cè)試 根據(jù)軟件產(chǎn)品的內(nèi)部工作過程,在計(jì)算機(jī)上進(jìn)行測(cè)試,以證實(shí)每種內(nèi)部操作是否符合設(shè)計(jì)規(guī)格要求,所有內(nèi)部成分是否已經(jīng)過檢查。這種測(cè)試方法就是白盒測(cè)試。白盒測(cè)試把測(cè)試對(duì)象看做一個(gè)打開的盒子,允許測(cè)試人員利用程序內(nèi)部的邏輯結(jié)構(gòu)及有關(guān)信息,設(shè)計(jì)或選擇測(cè)試用例,對(duì)程序所有邏輯路徑進(jìn)行測(cè)試。通過在不同點(diǎn)檢查程序的狀態(tài),確定實(shí)際的狀態(tài)是否與預(yù)期的狀態(tài)一致。 不論黑盒測(cè)試,還是白盒測(cè)試,都不可能進(jìn)行所謂的窮舉測(cè)試。任何軟件開發(fā)項(xiàng)目都要受到期限、費(fèi)用、人力和機(jī)時(shí)等條件的限制,為了節(jié)省時(shí)間和資源,提高測(cè)試效率,就必須要從數(shù)量極大的可用測(cè)試用例中精心地挑選少量的測(cè)試數(shù)據(jù),使得采用這些測(cè)試數(shù)據(jù)能夠達(dá)到最佳的測(cè)試效果,能夠高效率地把隱藏的錯(cuò)誤揭露出來。 3 基于風(fēng)險(xiǎn)的測(cè)試 基于風(fēng)險(xiǎn)的測(cè)試是指評(píng)估測(cè)試的優(yōu)先級(jí),先做高優(yōu)先級(jí)的測(cè)試,如果時(shí)間或精力不夠,低優(yōu)先級(jí)的測(cè)試可以暫時(shí)先不做。如圖5 ,橫軸代表影響,豎軸代表概率,根據(jù)一個(gè)軟件的特點(diǎn)來確定:如果一個(gè)功能出了問題,它對(duì)整個(gè)產(chǎn)品的影響有多大,這個(gè)功能出問題的概率有多大?如果出問題的概率很大,出了問題對(duì)整個(gè)產(chǎn)品的影響也很大,那么在測(cè)試時(shí)就一定要覆蓋到。對(duì)于一個(gè)用戶很少用到的功能,出問題的概率很小,就算出了問題的影響也不是很大,那么如果時(shí)間比較緊的話,就可以考慮不測(cè)試。
圖5 基于風(fēng)險(xiǎn)測(cè)試的兩個(gè)決定因素就是:該功能出問題對(duì)用戶的影響有多大,出問題的概率有多大。其它一些影響因素還有復(fù)雜性、可用性、依賴性、可修改性等。測(cè)試人員主要根據(jù)事情的輕重緩急來決定測(cè)試工作的重點(diǎn)。 4基于模型的測(cè)試 模型實(shí)際上就是用語言把一個(gè)系統(tǒng)的行為描述出來,定義出它可能的各種狀態(tài),以及它們之間的轉(zhuǎn)換關(guān)系,即狀態(tài)轉(zhuǎn)換圖。模型是系統(tǒng)的抽象?;谀P偷臏y(cè)試是利用模型來生成相應(yīng)的測(cè)試用例,然后根據(jù)實(shí)際結(jié)果和原先預(yù)想的結(jié)果的差異來測(cè)試系統(tǒng),過程如圖6所示。
圖6 4.2邏輯覆蓋邏輯覆蓋是以程序內(nèi)部邏輯結(jié)構(gòu)為基礎(chǔ)來設(shè)計(jì)測(cè)試用例的技術(shù),屬白盒測(cè)試。這一方法要求測(cè)試人員對(duì)程序的邏輯結(jié)構(gòu)有清楚的了解,甚至要能掌握源程序的所有細(xì)節(jié)。由于覆蓋測(cè)試的目標(biāo)不同,邏輯覆蓋又可分為:語句覆蓋、判定覆蓋、判定-條件覆蓋、條件組合覆蓋及路徑覆蓋。 ① 語句覆蓋 :語句覆蓋就是設(shè)計(jì)若干個(gè)測(cè)試用例,運(yùn)行被測(cè)程序,使得每一可執(zhí)行語句至少執(zhí)行一次。這種覆蓋又稱為點(diǎn)覆蓋,它使得程序中每個(gè)可執(zhí)行語句都得到執(zhí)行,但它是最弱的邏輯覆蓋,效果有限,必須與其它方法交互使用。 ② 判定覆蓋 :判定覆蓋就是設(shè)計(jì)若干個(gè)測(cè)試用例,運(yùn)行被測(cè)程序,使得程序中每個(gè)判斷的取真分支和取假分支至少經(jīng)歷一次。判定覆蓋又稱為分支覆蓋。 判定覆蓋只比語句覆蓋稍強(qiáng)一些,但實(shí)際效果表明,只是判定覆蓋,還不能保證一定能查出在判斷的條件中存在的錯(cuò)誤。因此,還需要更強(qiáng)的邏輯覆蓋準(zhǔn)則去檢驗(yàn)判斷內(nèi)部條件。 ③ 條件覆蓋 :條件覆蓋就是設(shè)計(jì)若干個(gè)測(cè)試用例,運(yùn)行被測(cè)程序,使得程序中每個(gè)判斷的每個(gè)條件的可能取值至少執(zhí)行一次。 條件覆蓋深入到判定中的每個(gè)條件,但可能不能滿足判定覆蓋的要求。 ④ 判定-條件覆蓋 :判定-條件覆蓋就是設(shè)計(jì)足夠的測(cè)試用例,使得判斷中每個(gè)條件的所有可能取值至少執(zhí)行一次,同時(shí)每個(gè)判斷本身的所有可能判斷結(jié)果至少執(zhí)行一次。換言之,即是要求各個(gè)判斷的所有可能的條件取值組合至少執(zhí)行一次。 判定-條件覆蓋有缺陷。從表面上來看,它測(cè)試了所有條件的取值。但是事實(shí)并非如此。往往某些條件掩蓋了另一些條件。會(huì)遺漏某些條件取值錯(cuò)誤的情況。為徹底地檢查所有條件的取值,需要將判定語句中給出的復(fù)合條件表達(dá)式進(jìn)行分解,形成由多個(gè)基本判定嵌套的流程圖。這樣就可以有效地檢查所有的條件是否正確了。 ⑤ 多重條件覆蓋 :多重條件覆蓋就是設(shè)計(jì)足夠的測(cè)試用例,運(yùn)行被測(cè)程序,使得每個(gè)判斷的所有可能的條件取值組合至少執(zhí)行一次。 這是一種相當(dāng)強(qiáng)的覆蓋準(zhǔn)則,可以有效地檢查各種可能的條件取值的組合是否正確。它不但可覆蓋所有條件的可能取值的組合,還可覆蓋所有判斷的可取分支,但可能有的路徑會(huì)遺漏掉。測(cè)試還不完全。 6 路徑測(cè)試 :路徑測(cè)試就是設(shè)計(jì)足夠的測(cè)試用例,覆蓋程序中所有可能的路徑。這是最強(qiáng)的覆蓋準(zhǔn)則。但在路徑數(shù)目很大時(shí),真正做到完全覆蓋是很困難的,必須把覆蓋路徑數(shù)目壓縮到一定限度。 (2) 判定覆蓋 所謂判定覆蓋就是設(shè)計(jì)若干個(gè)測(cè)試用例,運(yùn)行被測(cè)程序,使得程序中每個(gè)判斷的取真分支和取假分支至少經(jīng)歷一次。判定覆蓋又稱為分支覆蓋。 (3) 條件覆蓋 所謂條件覆蓋就是設(shè)計(jì)若干個(gè)測(cè)試用例,運(yùn)行被測(cè)程序,使得程序中每個(gè)判斷的每個(gè)條件的可能取值至少執(zhí)行一次。例如在本題所給出的例子中,我們事先可對(duì)所有條件的取值加以標(biāo)記。 (4) 判定-條件覆蓋 所謂判定-條件覆蓋就是設(shè)計(jì)足夠的測(cè)試用例,使得判斷中每個(gè)條件的所有可能取值至少執(zhí)行一次,同時(shí)每個(gè)判斷本身的所有可能判斷結(jié)果至少執(zhí)行一次。換言之,即是要求各個(gè)判斷的所有可能的條件取值組合至少執(zhí)行一次 (5) 條件組合覆蓋 所謂條件組合覆蓋就是設(shè)計(jì)足夠的測(cè)試用例,運(yùn)行被測(cè)程序,使得每個(gè)判斷的所有可能的條件取值組合至少執(zhí)行一次。 (6) 路徑測(cè)試 路徑測(cè)試就是設(shè)計(jì)足夠的測(cè)試用例,覆蓋程序中所有可能的路徑。
4.3 等價(jià)類劃分等價(jià)類劃分是一種典型的黑盒測(cè)試方法。使用這一方法時(shí),完全不考慮程序的內(nèi)部結(jié)構(gòu),只依據(jù)程序的規(guī)格說明來設(shè)計(jì)測(cè)試用例。由于不可能用所有可以輸入的數(shù)據(jù)來測(cè)試程序,而只能從全部可供輸入的數(shù)據(jù)中選擇一個(gè)子集進(jìn)行測(cè)試。如何選擇適當(dāng)?shù)淖蛹?,使其盡可能多地發(fā)現(xiàn)錯(cuò)誤。解決的辦法之一就是等價(jià)類劃分。 1 把數(shù)目極多的輸入數(shù)據(jù)(有效的和無效的)劃分為若干等價(jià)類。所謂等價(jià)類是指某個(gè)輸入域的子集合,在該子集合中,各個(gè)輸入數(shù)據(jù)對(duì)于揭露程序中的錯(cuò)誤都是等效的。并合理地假定:測(cè)試某等價(jià)類的代表值就等價(jià)于對(duì)這一類其它值的測(cè)試。因此,我們可以把全部輸入資料合理劃分為若干等價(jià)類,在每一個(gè)等價(jià)類中取一個(gè)數(shù)據(jù)做為測(cè)試的輸入條件,就可用少量代表性測(cè)試數(shù)據(jù),取得較好的測(cè)試效果。 等價(jià)類的劃分有兩種不同的情況: § 有效等價(jià)類:是指對(duì)于程序規(guī)格說明來說,是合理的,有意義的輸入數(shù)據(jù)構(gòu)成的集合。利用它,可以檢驗(yàn)程序是否實(shí)現(xiàn)了規(guī)格說明預(yù)先規(guī)定的功能和性能。 § 無效等價(jià)類:是指對(duì)于程序規(guī)格說明來說,是不合理的,無意義的輸入數(shù)據(jù)構(gòu)成的集合。利用它,可以檢查程序中功能和性能的實(shí)現(xiàn)是否有不符合規(guī)格說明要求的地方。 在設(shè)計(jì)測(cè)試用例時(shí),要同時(shí)考慮有效等價(jià)類和無效等價(jià)類的設(shè)計(jì)。軟件不能都只接收合理的數(shù)據(jù),還要經(jīng)受意外的考驗(yàn),接受無效的或不合理的數(shù)據(jù),這樣獲得的軟件才能具有較高的可靠性。劃分等價(jià)類的原則如下: § 按區(qū)間劃分:如果可能的輸入數(shù)據(jù)屬于一個(gè)取值范圍或值的個(gè)數(shù)限制范圍,則可以確立一個(gè)有效等價(jià)類和兩個(gè)無效等價(jià)類。 § 按數(shù)值劃分:如果規(guī)定了輸入數(shù)據(jù)的一組值,而且程序要對(duì)每個(gè)輸入值分別進(jìn)行處理。則可為每一個(gè)輸入值確立一個(gè)有效等價(jià)類,此外針對(duì)這組值確立一個(gè)無效等價(jià)類,它是所有不允許的輸入值的集合。 § 按數(shù)值集合劃分:如果可能的輸入數(shù)據(jù)屬于一個(gè)值的集合,或者須滿足“必須如何”的條件,這時(shí)可確立一個(gè)有效等價(jià)類和一個(gè)無效等價(jià)類。 § 按限制條件或規(guī)則劃分:如果規(guī)定了輸入數(shù)據(jù)必須遵守的規(guī)則或限制條件,則可以確立一個(gè)有效等價(jià)類(符合規(guī)則)和若干個(gè)無效等價(jià)類(從不同角度違反規(guī)則)。 ② 確立測(cè)試用例 在確立了等價(jià)類之后,建立等價(jià)類表,列出所有劃分出的等價(jià)類: 再從劃分出的等價(jià)類中按以下原則選擇測(cè)試用例: § 設(shè)計(jì)盡可能少的測(cè)試用例,覆蓋所有的有效等價(jià)類; § 針對(duì)每一個(gè)無效等價(jià)類,設(shè)計(jì)一個(gè)測(cè)試用例來覆蓋它。
4.4邊界值分析邊界值的分析是利用了一個(gè)規(guī)律,即程序最容易發(fā)生錯(cuò)誤的地方就是在邊界值的附近,它取決于變量的類型,以及變量的取值范圍。比如,在做三角形計(jì)算時(shí),要輸入三角形的三個(gè)邊長:A、B和C。 我們應(yīng)注意到這三個(gè)數(shù)值應(yīng)當(dāng)滿足A>0、B>0、C>0、A+B>C、A+C>B、B+C>A,才能構(gòu)成三角形。但如果把六個(gè)不等式中的任何一個(gè)大于號(hào)“>”錯(cuò)寫成大于等于號(hào)“≥”,那就不能構(gòu)成三角形。問題恰出現(xiàn)在容易被疏忽的邊界附近。這里所說的邊界是指,相當(dāng)于輸入等價(jià)類和輸出等價(jià)類而言,稍高于其邊界值及稍低于其邊界值的一些特定情況。 使用邊界值分析方法設(shè)計(jì)測(cè)試用例,首先應(yīng)確定邊界情況。通常輸入等價(jià)類與輸出等價(jià)類的邊界,就是應(yīng)著重測(cè)試的邊界情況。應(yīng)當(dāng)選取正好等于,剛剛大于,或剛剛小于邊界的值做為測(cè)試數(shù)據(jù),而不是選取等價(jià)類中的典型值或任意值做為測(cè)試資料。一般對(duì)于有n個(gè)變量時(shí),會(huì)有6n+1個(gè)測(cè)試用例,取值分別是min-1, min, min+1, normal, max-1, max,max+1的組合。 邊界值分析方法是最有效的黑盒測(cè)試方法,但當(dāng)邊界情況很復(fù)雜的時(shí)候,要找出適當(dāng)?shù)臏y(cè)試用例還需針對(duì)問題的輸入域、輸出域邊界,耐心細(xì)致地逐個(gè)考慮。
4.5錯(cuò)誤推測(cè)法人們也可以靠經(jīng)驗(yàn)和直覺推測(cè)程序中可能存在的各種錯(cuò)誤,從而有針對(duì)性地編寫檢查這些錯(cuò)誤的例子。這就是錯(cuò)誤推測(cè)法。 錯(cuò)誤推測(cè)法的基本想法是:列舉出程序中所有可能有的錯(cuò)誤和容易發(fā)生錯(cuò)誤的特殊情況,根據(jù)它們選擇測(cè)試用例。例如,在介紹單元測(cè)試時(shí)曾列出許多在模塊中常見的錯(cuò)誤,這些是單元測(cè)試經(jīng)驗(yàn)的總結(jié)。此外,對(duì)于在程序中容易出錯(cuò)的情況,也有一些經(jīng)驗(yàn)總結(jié)出來。例如,輸入數(shù)據(jù)為0,或輸出數(shù)據(jù)為0是容易發(fā)生錯(cuò)誤的情形,因此可選擇輸入數(shù)據(jù)為0,或使輸出數(shù)據(jù)為0的例子作為測(cè)試用例。又例如,輸入表格為空或輸入表格只有一行,也是容易發(fā)生錯(cuò)誤的情況。可選擇表示這種情況的例子作為測(cè)試用例。再例如,可以針對(duì)一個(gè)排序程序,輸入空的值(沒有數(shù)據(jù))、輸入一個(gè)數(shù)據(jù)、讓所有的輸入數(shù)據(jù)都相等、讓所有輸入數(shù)據(jù)有序排列、讓所有輸入數(shù)據(jù)逆序排列等,進(jìn)行錯(cuò)誤推測(cè)。 4.6因果圖前面介紹的等價(jià)類劃分方法和邊界值分析方法,都是著重考慮輸入條件,但未考慮輸入條件之間的聯(lián)系。如果在測(cè)試時(shí)必須考慮輸入條件的各種組合,可能的組合數(shù)將是天文數(shù)字。因此必須考慮使用一種適合于描述對(duì)于多種條件的組合,相應(yīng)產(chǎn)生多個(gè)動(dòng)作的形式來考慮設(shè)計(jì)測(cè)試用例,這就需要利用因果圖。 因果圖方法最終生成的就是判定表。它適合于檢查程序輸入條件的各種組合情況。 利用因果圖生成測(cè)試用例的基本步驟是: § 分析軟件規(guī)格說明描述中,哪些是原因(即輸入條件或輸入條件的等價(jià)類),哪些是結(jié)果(即輸出條件),并給每個(gè)原因和結(jié)果賦予一個(gè)標(biāo)識(shí)符。 § 分析軟件規(guī)格說明描述中的語義,找出原因與結(jié)果之間,原因與原因之間對(duì)應(yīng)的是什么關(guān)系? 根據(jù)這些關(guān)系,畫出因果圖。 § 由于語法或環(huán)境限制,有些原因與原因之間,原因與結(jié)果之間的組合情況不可能出現(xiàn)。為表明這些特殊情況,在因果圖上用一些記號(hào)標(biāo)明約束或限制條件。 § 把因果圖轉(zhuǎn)換成判定表。 § 把判定表的每一列拿出來作為依據(jù),設(shè)計(jì)測(cè)試用例。 通常,在因果圖中,用Ci表示原因,Ei表示結(jié)果,其基本符號(hào)如圖7所示。各結(jié)點(diǎn)表示狀態(tài),可取值“0”或“1”。“0”表示某狀態(tài)不出現(xiàn),“1”表示某狀態(tài)出現(xiàn)。 § 恒等:若原因出現(xiàn),則結(jié)果出現(xiàn)。若原因不出現(xiàn),則結(jié)果也不出現(xiàn)。 § 非:若原因出現(xiàn),則結(jié)果不出現(xiàn)。若原因不出現(xiàn),反而結(jié)果出現(xiàn)。 § 或(∨):若幾個(gè)原因中有一個(gè)出現(xiàn),則結(jié)果出現(xiàn),幾個(gè)原因都不出現(xiàn),結(jié)果不出現(xiàn)。 § 與(∧):若幾個(gè)原因都出現(xiàn),結(jié)果才出現(xiàn)。若其中有一個(gè)原因不出現(xiàn),結(jié)果不出現(xiàn)。
圖7 因果圖的圖形符號(hào) 為了表示原因與原因之間,結(jié)果與結(jié)果之間可能存在的約束條件,在因果圖中可以附加一些表示約束條件的符號(hào)。從輸入(原因)考慮,有四種約束;從輸出(結(jié)果)考慮,還有一種約束,參看圖8: § E(互斥):表示a,b兩個(gè)原因不會(huì)同時(shí)成立,兩個(gè)中最多有一個(gè)可能成立。 § M(屏蔽):表示當(dāng)a是1時(shí),b必須是0。而當(dāng)a為0時(shí),b的值不定。
圖8 因果圖的約束符號(hào) 因果圖方法是一個(gè)非常有效的黑盒測(cè)試方法,它能夠生成沒有重復(fù)性的且發(fā)現(xiàn)錯(cuò)誤能力強(qiáng)的測(cè)試用例,而且對(duì)輸入、輸出同時(shí)進(jìn)行了分析。 4.7測(cè)試方法選擇的綜合策略Myers提出了使用各種測(cè)試方法的綜合策略: § 在任何情況下都必須使用邊界值分析方法。經(jīng)驗(yàn)表明用這種方法設(shè)計(jì)出測(cè)試用例發(fā)現(xiàn)程序錯(cuò)誤的能力最強(qiáng)。 § 必要時(shí)用等價(jià)類劃分方法補(bǔ)充一些測(cè)試用例。 § 用錯(cuò)誤推測(cè)法再追加一些測(cè)試用例。 § 對(duì)照程序邏輯,檢查已設(shè)計(jì)出的測(cè)試用例的邏輯覆蓋程度。如果沒有達(dá)到要求的覆蓋標(biāo)準(zhǔn),應(yīng)當(dāng)再補(bǔ)充足夠的測(cè)試用例。 § 如果程序的功能說明中含有輸入條件的組合情況,則一開始就可選用因果圖法。 5. 程序的靜態(tài)測(cè)試5.1源程序靜態(tài)分析通常采用以下一些方法進(jìn)行源程序的靜態(tài)分析。 ① 生成各種引用表 § 直接從表中查出說明/使用錯(cuò)誤等。如,循環(huán)層次表、變量交叉引用表、標(biāo)號(hào)交叉引用表等。 § 為用戶提供輔助信息。如,子程序(宏、函數(shù))引用表、等價(jià)(變量、標(biāo)號(hào))表、常數(shù)表等。 § 用來做錯(cuò)誤預(yù)測(cè)和程序復(fù)雜度計(jì)算。如,操作符和操作數(shù)的統(tǒng)計(jì)表等。 ② 靜態(tài)錯(cuò)誤分析 靜態(tài)錯(cuò)誤分析主要用于確定在源程序中是否有某類錯(cuò)誤或“危險(xiǎn)”結(jié)構(gòu)。 § 類型和單位分析 :為了強(qiáng)化對(duì)源程序中數(shù)據(jù)類型的檢查,發(fā)現(xiàn)在數(shù)據(jù)類型上的錯(cuò)誤和單位上的不一致性,在程序設(shè)計(jì)語言中擴(kuò)充了一些結(jié)構(gòu)。如單位分析要求使用一種預(yù)處理器,它能夠通過使用一般的組合/消去規(guī)則,確定表達(dá)式的單位。 § 引用分析 :最廣泛使用的靜態(tài)錯(cuò)誤分析方法就是發(fā)現(xiàn)引用異常。如果沿著程序的控制路徑,變量在賦值以前被引用,或變數(shù)在賦值以后未被引用,這時(shí)就發(fā)生了引用異常。為了檢測(cè)引用異常,需要檢查通過程序的每一條路徑。也可以建立引用異常的探測(cè)工具。 § 表達(dá)式分析 :對(duì)表達(dá)式進(jìn)行分析,以發(fā)現(xiàn)和糾正在表達(dá)式中出現(xiàn)的錯(cuò)誤。包括:在表達(dá)式中不正確地使用了括號(hào)造成錯(cuò)誤。數(shù)組下標(biāo)越界造成錯(cuò)誤。除式為零造成錯(cuò)誤。對(duì)負(fù)數(shù)開平方,或?qū)?#960;求正切值造成錯(cuò)誤。以及對(duì)浮點(diǎn)數(shù)計(jì)算的誤差進(jìn)行檢查。 § 界面分析 :關(guān)于接口的靜態(tài)錯(cuò)誤分析主要檢查過程、函數(shù)過程之間接口的一致性。因此要檢查形參與實(shí)參在類型、數(shù)量、維數(shù)、順序、使用上的一致性;檢查全局變量和公共數(shù)據(jù)區(qū)在使用上的一致性。 5.2人工測(cè)試靜態(tài)分析中進(jìn)行人工測(cè)試的主要方法有桌前檢查、代碼審查和走查。經(jīng)驗(yàn)表明,使用這種方法能夠有效地發(fā)現(xiàn)30%到70%的邏輯設(shè)計(jì)和編碼錯(cuò)誤。 ① 桌前檢查(Desk Checking) 由程序員自己檢查自己編寫的程序。程序員在程序通過編譯之后,進(jìn)行單元測(cè)試設(shè)計(jì)之前,對(duì)源程序代碼進(jìn)行分析,檢驗(yàn),并補(bǔ)充相關(guān)的文文件,目的是發(fā)現(xiàn)程序中的錯(cuò)誤。檢查項(xiàng)目有: § 檢查變數(shù)的交叉引用表 :重點(diǎn)是檢查未說明的變量和違反了類型規(guī)定的變量;還要對(duì)照源程序,逐個(gè)檢查變量的引用、變量的使用序列;臨時(shí)變量在某條路徑上的重寫情況;局部變量、全局變量與特權(quán)變量的使用; § 檢查標(biāo)號(hào)的交叉引用表 :驗(yàn)證所有標(biāo)號(hào)的正確性:檢查所有標(biāo)號(hào)的命名是否正確;轉(zhuǎn)向指定位置的標(biāo)號(hào)是否正確。 § 檢查子程序、宏、函數(shù) :驗(yàn)證每次調(diào)用與被調(diào)用位置是否正確;確認(rèn)每次被調(diào)用的子程序、宏、函數(shù)是否存在;檢驗(yàn)調(diào)用序列中調(diào)用方式與參數(shù)順序、個(gè)數(shù)、類型上的一致性。 § 等值性檢查 :檢查全部等價(jià)變量的類型的一致性,解釋所包含的類型差異。 § 常量檢查 :確認(rèn)每個(gè)常量的取值和數(shù)制、數(shù)據(jù)類型;檢查常量每次引用同它的取值、數(shù)制和類型的一致性; § 標(biāo)準(zhǔn)檢查 :用標(biāo)準(zhǔn)檢查程序或手工檢查程序中違反標(biāo)準(zhǔn)的問題。 § 風(fēng)格檢查 :檢查在程序設(shè)計(jì)風(fēng)格方面發(fā)現(xiàn)的問題。 § 比較控制流 :比較由程序員設(shè)計(jì)的控制流圖和由實(shí)際程序生成的控制流圖,尋找和解釋每個(gè)差異,修改文檔和校正錯(cuò)誤。 § 選擇、啟動(dòng)路徑 :在程序員設(shè)計(jì)的控制流圖上選擇路徑,再到實(shí)際的控制流圖上啟動(dòng)這條路徑。如果選擇的路徑在實(shí)際控制流圖上不能啟動(dòng),則源程序可能有錯(cuò)。用這種方法啟動(dòng)的路徑集合應(yīng)保證源程序模塊的每行代碼都被檢查,即桌前檢查應(yīng)至少是語句覆蓋。 § 對(duì)照程序的規(guī)格說明,詳細(xì)閱讀源代碼 :程序員對(duì)照程序的規(guī)格說明書、規(guī)定的算法和程序設(shè)計(jì)語言的語法規(guī)則,仔細(xì)地閱讀源代碼,逐字逐句進(jìn)行分析和思考,比較實(shí)際的代碼和期望的代碼,從它們的差異中發(fā)現(xiàn)程序的問題和錯(cuò)誤。 § 補(bǔ)充文檔 :桌前檢查的文檔是一種過渡性的文檔,不是公開的正式文檔。通過編寫文文件,也是對(duì)程序的一種下意識(shí)的檢查和測(cè)試,可以幫助程序員發(fā)現(xiàn)和抓住更多的錯(cuò)誤。 這種桌前檢查,由于程序員熟悉自己的程序和自身的程序設(shè)計(jì)風(fēng)格,可以節(jié)省很多的檢查時(shí)間,但應(yīng)避免主觀片面性。 ② 代碼會(huì)審(Code Reading Review) 代碼會(huì)審是由若干程序員和測(cè)試員組成一個(gè)會(huì)審小組,通過閱讀、討論和爭(zhēng)議,對(duì)程序進(jìn)行靜態(tài)分析的過程。 代碼會(huì)審分兩步:第一步,小組負(fù)責(zé)人提前把設(shè)計(jì)規(guī)格說明書、控制流程圖、程序文本及有關(guān)要求、規(guī)范等分發(fā)給小組成員,作為評(píng)審的依據(jù)。小組成員在充分閱讀這些材料之后,進(jìn)入審查的第二步:召開程序?qū)彶闀?huì)。在會(huì)上,首先由程序員逐句講解程序的邏輯。在此過程中,程序員或其它小組成員可以提出問題,展開討論,審查錯(cuò)誤是否存在。實(shí)踐表明,程序員在講解過程中能發(fā)現(xiàn)許多原來自己沒有發(fā)現(xiàn)的錯(cuò)誤,而討論和爭(zhēng)議則促進(jìn)了問題的暴露。 在會(huì)前,應(yīng)當(dāng)給會(huì)審小組每個(gè)成員準(zhǔn)備一份常見錯(cuò)誤的清單,把以往所有可能發(fā)生的常見錯(cuò)誤羅列出來,供與會(huì)者對(duì)照檢查,以提高會(huì)審的實(shí)效。這個(gè)常見錯(cuò)誤清單也叫做檢查表,它把程序中可能發(fā)生的各種錯(cuò)誤進(jìn)行分類,對(duì)每一類列舉出盡可能多的典型錯(cuò)誤,然后把它們制成表格,供在會(huì)審時(shí)使用。這種檢查表類似于本章單元測(cè)試中給出的檢查表。 ③ 走查(Walkthroughs) 走查與代碼會(huì)審基本相同,其過程分為兩步。第一步也把材料先發(fā)給走查小組每個(gè)成員,讓他們認(rèn)真研究程序,然后再開會(huì)。開會(huì)的程序與代碼會(huì)審不同,不是簡單地讀程序和對(duì)照錯(cuò)誤檢查表進(jìn)行檢查,而是讓與會(huì)者“充當(dāng)”計(jì)算機(jī)。即首先由測(cè)試組成員為被測(cè)程序準(zhǔn)備一批有代表性的測(cè)試用例,提交給走查小組。走查小組開會(huì),集體扮演計(jì)算機(jī)角色,讓測(cè)試用例沿程序的邏輯運(yùn)行一遍,隨時(shí)記錄程序的蹤跡,供分析和討論用。 人們借助于測(cè)試用例的媒介作用,對(duì)程序的邏輯和功能提出各種疑問,結(jié)合問題開展熱烈的討論和爭(zhēng)議,能夠發(fā)現(xiàn)更多的問題。 6. 調(diào)試(Debug,排錯(cuò))軟件測(cè)試也是一個(gè)系統(tǒng)工程,在做測(cè)試時(shí),需要先做測(cè)試計(jì)劃和規(guī)格說明,然后設(shè)計(jì)測(cè)試用例,定義策略,最后將測(cè)試結(jié)果與預(yù)先給出的期望結(jié)果進(jìn)行比較,再做評(píng)價(jià)分析。而軟件調(diào)試則是在進(jìn)行了成功的測(cè)試之后才開始的工作。它與軟件測(cè)試不同,軟件測(cè)試的目的是盡可能多地發(fā)現(xiàn)軟件中的錯(cuò)誤,但進(jìn)一步診斷和改正程序中潛在的錯(cuò)誤,則是調(diào)試的任務(wù)。 調(diào)試活動(dòng)由兩部分組成: ① 確定程序中可疑錯(cuò)誤的確切性質(zhì)和位置。 ② 對(duì)程序(設(shè)計(jì),編碼)進(jìn)行修改,排除這個(gè)錯(cuò)誤。 通常,調(diào)試工作是一個(gè)具有很強(qiáng)技巧性的工作。一個(gè)軟件工程人員在分析測(cè)試結(jié)果的時(shí)候會(huì)發(fā)現(xiàn),軟件運(yùn)行失效或出現(xiàn)問題,往往只是潛在錯(cuò)誤的外部表現(xiàn),而外部表現(xiàn)與內(nèi)在原因之間常常沒有明顯的聯(lián)系。如果要找出真正的原因,排除潛在的錯(cuò)誤,不是一件易事。因此可以說,調(diào)試是通過現(xiàn)象,找出原因的一個(gè)思維分析的過程。 6.1調(diào)試的步驟① 從錯(cuò)誤的外部表現(xiàn)形式入手,確定程序中出錯(cuò)位置; ② 研究有關(guān)部分的程序,找出錯(cuò)誤的內(nèi)在原因; ③ 修改設(shè)計(jì)和代碼,以排除這個(gè)錯(cuò)誤; ④ 重復(fù)進(jìn)行暴露了這個(gè)錯(cuò)誤的原始測(cè)試或某些有關(guān)測(cè)試,以確認(rèn)該錯(cuò)誤是否被排除;是否引進(jìn)了新的錯(cuò)誤。 ⑤ 如果所做的修正無效,則撤銷這次改動(dòng),重復(fù)上述過程,直到找到一個(gè)有效的解決辦法為止。 從技術(shù)角度來看,查找錯(cuò)誤的難度在于: § 現(xiàn)象與原因所處的位置可能相距甚遠(yuǎn)。就是說,現(xiàn)象可能出現(xiàn)在程序的一個(gè)部位,而原因可能在離此很遠(yuǎn)的另一個(gè)位置。高耦合的程序結(jié)構(gòu)中這種情況更為明顯。 § 當(dāng)糾正其它錯(cuò)誤時(shí),這一錯(cuò)誤所表現(xiàn)出的現(xiàn)象可能會(huì)暫時(shí)消失,但并未實(shí)際排除。 § 現(xiàn)象實(shí)際上是由一些非錯(cuò)誤原因(例如,舍入得不精確)引起的。 § 現(xiàn)象可能是由于一些不容易發(fā)現(xiàn)的人為錯(cuò)誤引起的。 § 錯(cuò)誤是由于時(shí)序問題引起的,與處理過程無關(guān)。 § 現(xiàn)像是由于難于精確再現(xiàn)的輸入狀態(tài)(例如,實(shí)時(shí)應(yīng)用中輸入順序不確定)引起。 § 現(xiàn)象可能是周期出現(xiàn)的。在軟、硬件結(jié)合的嵌入式系統(tǒng)中常常遇到。 6.2幾種主要的調(diào)試方法調(diào)試的關(guān)鍵在于推斷程序內(nèi)部的錯(cuò)誤位置及原因。為此,可以采用以下方法: ① 強(qiáng)行排錯(cuò) 這是目前使用較多,效率較低的調(diào)試方法。它不需要過多的思考,比較省腦筋。例如: § 通過內(nèi)存全部打印來排錯(cuò)(Memory Dump); § 在程序特定部位設(shè)置打印語句; § 自動(dòng)調(diào)試工具。 可供利用的典型的語言功能有:打印出語句執(zhí)行的追蹤信息,追蹤子程序調(diào)用,以及指定變量的變化情況。自動(dòng)調(diào)試工具的功能是:設(shè)置斷點(diǎn),當(dāng)程序執(zhí)行到某個(gè)特定的語句或某個(gè)特定的變量值改變時(shí),程序暫停執(zhí)行。程序員可在終端上觀察程序此時(shí)的狀態(tài)。 應(yīng)用以上任一種方法之前,都應(yīng)當(dāng)對(duì)錯(cuò)誤的征兆進(jìn)行全面徹底的分析,得出對(duì)出錯(cuò)位置及錯(cuò)誤性質(zhì)的推測(cè),再使用一種適當(dāng)?shù)呐佩e(cuò)方法來檢驗(yàn)推測(cè)的正確性。 ② 回溯法排錯(cuò) 這是在小程序中常用的一種有效的排錯(cuò)方法。一旦發(fā)現(xiàn)了錯(cuò)誤,人們先分析錯(cuò)誤征兆,確定最先發(fā)現(xiàn)“癥狀”的位置。然后,人工沿程序的控制流程,向回追蹤源程序代碼,直到找到錯(cuò)誤根源或確定錯(cuò)誤產(chǎn)生的范圍。 回溯法對(duì)于小程序很有效,往往能把錯(cuò)誤范圍縮小到程序中的一小段代碼;仔細(xì)分析這段代碼不難確定出錯(cuò)的準(zhǔn)確位置。但對(duì)于大程序,由于回溯的路徑數(shù)目較多,回溯會(huì)變得很困難。 ③ 歸納法排錯(cuò) 歸納法是一種從特殊推斷一般的系統(tǒng)化思考方法。歸納法排錯(cuò)的基本思想是:從一些線索(錯(cuò)誤征兆)著手,通過分析它們之間的關(guān)系來找出錯(cuò)誤。 歸納法排錯(cuò)步驟大致分為以下四步: § 收集有關(guān)的資料 :列出所有已知的測(cè)試用例和程序執(zhí)行結(jié)果??茨男┹斎霐?shù)據(jù)的運(yùn)行結(jié)果是正確的,哪些輸入數(shù)據(jù)的運(yùn)行結(jié)果有錯(cuò)誤存在。 § 組織數(shù)據(jù) :由于歸納法是從特殊到一般的推斷過程,所以需要組織整理數(shù)據(jù),以便發(fā)現(xiàn)規(guī)律。常用的構(gòu)造線索的技術(shù)是“分類法”。
而在“Yes”和“No”這兩列中,“Yes”描述了出現(xiàn)錯(cuò)誤的現(xiàn)象的3W1H,“No”作為比較,描述了沒有錯(cuò)誤的現(xiàn)象的3W1H。通過分析,找出矛盾來。 § 提出假設(shè) :分析線索之間的關(guān)系,利用在線索結(jié)構(gòu)中觀察到的矛盾現(xiàn)象,設(shè)計(jì)一個(gè)或多個(gè)關(guān)于出錯(cuò)原因的假設(shè)。如果一個(gè)假設(shè)也提不出來,歸納過程就需要收集更多的數(shù)據(jù)。此時(shí),應(yīng)當(dāng)再設(shè)計(jì)與執(zhí)行一些測(cè)試用例,以獲得更多的資料。如果提出了許多假設(shè),則首先選用最有可能成為出錯(cuò)原因的假設(shè)。 § 證明假設(shè) :把假設(shè)與原始線索或數(shù)據(jù)進(jìn)行比較,若它能完全解釋一切現(xiàn)象,則假設(shè)得到證明;否則,就認(rèn)為假設(shè)不合理,或不完全,或是存在多個(gè)錯(cuò)誤,以致只能消除部分錯(cuò)誤。 ④ 演繹法排錯(cuò) 演繹法是一種從一般原理或前提出發(fā),經(jīng)過排除和精化的過程來推導(dǎo)出結(jié)論的思考方法。演繹法排錯(cuò)是測(cè)試人員首先根據(jù)已有的測(cè)試用例,設(shè)想及枚舉出所有可能出錯(cuò)的原因做為假設(shè);然后再用原始測(cè)試數(shù)據(jù)或新的測(cè)試,從中逐個(gè)排除不可能正確的假設(shè);最后,再用測(cè)試數(shù)據(jù)驗(yàn)證余下的假設(shè)確是出錯(cuò)的原因。 演繹法主要有以下四個(gè)步驟: § 列舉所有可能出錯(cuò)原因的假設(shè) :把所有可能的錯(cuò)誤原因列成表。它們不需要完全的解釋,而僅僅是一些可能因素的假設(shè)。通過它們,可以組織、分析現(xiàn)有數(shù)據(jù)。 § 利用已有的測(cè)試數(shù)據(jù),排除不正確的假設(shè) :仔細(xì)分析已有的數(shù)據(jù),尋找矛盾,力求排除前一步列出所有原因。如果所有原因都被排除了,則需要補(bǔ)充一些數(shù)據(jù)(測(cè)試用例),以建立新的假設(shè);如果保留下來的假設(shè)多于一個(gè),則選擇可能性最大的原因做基本的假設(shè)。 § 改進(jìn)余下的假設(shè) :利用已知的線索,進(jìn)一步改進(jìn)余下的假設(shè),使之更具體化,以便可以精確地確定出錯(cuò)位置。 § 證明余下的假設(shè) :這一步極端重要,具體做法與歸納法的第4步相同。 6.3調(diào)試原則在調(diào)試方面,許多原則本質(zhì)上是心理學(xué)方面的問題。因?yàn)檎{(diào)試由兩部分組成,所以調(diào)試原則也分成兩組。 ① 確定錯(cuò)誤的性質(zhì)和位置的原則 § 用頭腦去分析思考與錯(cuò)誤征兆有關(guān)的信息。最有效的調(diào)試方法是用頭腦分析與錯(cuò)誤征兆有關(guān)的信息。一個(gè)能干的程序調(diào)試員應(yīng)能做到不使用計(jì)算機(jī)就能夠確定大部分錯(cuò)誤。 § 避開死胡同。如果程序調(diào)試員走進(jìn)了死胡同,或者陷入了絕境,最好暫時(shí)把問題拋開,留到第二天再去考慮,或者向其它人講解這個(gè)問題。事實(shí)上常有這種情形:向一個(gè)好的聽眾簡單地描述這個(gè)問題時(shí),不需要任何聽講者的提示,你自己會(huì)突然發(fā)現(xiàn)問題的所在。 § 只把調(diào)試工具當(dāng)做輔助手段來使用。利用調(diào)試工具,可以幫助思考,但不能代替思考。因?yàn)檎{(diào)試工具給你的是一種無規(guī)律的調(diào)試方法。實(shí)驗(yàn)證明,即使是對(duì)一個(gè)不熟悉的程序進(jìn)行調(diào)試時(shí),不用工具的人往往比使用工具的人更容易成功。 § 避免用試探法,最多只能把它當(dāng)做最后手段。初學(xué)調(diào)試的人最常犯的一個(gè)錯(cuò)誤是想試試修改程序來解決問題。這還是一種碰運(yùn)氣的盲目的動(dòng)作,它的成功機(jī)會(huì)很小,而且還常把新的錯(cuò)誤帶到問題中來。 ② 修改錯(cuò)誤的原則 § 在出現(xiàn)錯(cuò)誤的地方,很可能還有別的錯(cuò)誤。經(jīng)驗(yàn)證明,錯(cuò)誤有群集現(xiàn)象,當(dāng)在某一程序段發(fā)現(xiàn)有錯(cuò)誤時(shí),在該程序段中還存在別的錯(cuò)誤的概率也很高。因此,在修改一個(gè)錯(cuò)誤時(shí),還要查一下它的近鄰,看是否還有別的錯(cuò)誤。 § 修改錯(cuò)誤的一個(gè)常見失誤是只修改了這個(gè)錯(cuò)誤的征兆或這個(gè)錯(cuò)誤的表現(xiàn),而沒有修改錯(cuò)誤的本身。如果提出的修改不能解釋與這個(gè)錯(cuò)誤有關(guān)的全部線索,那就表明了只修改了錯(cuò)誤的一部分。 § 當(dāng)心修正一個(gè)錯(cuò)誤的同時(shí)有可能會(huì)引入新的錯(cuò)誤。人們不僅需要注意不正確的修改,而且還要注意看起來是正確的修改可能會(huì)帶來的副作用,即引進(jìn)新的錯(cuò)誤。因此在修改了錯(cuò)誤之后,必須進(jìn)行回歸測(cè)試,以確認(rèn)是否引進(jìn)了新的錯(cuò)誤。 § 修改錯(cuò)誤的過程將迫使人們暫時(shí)回到程序設(shè)計(jì)階段。修改錯(cuò)誤也是程序設(shè)計(jì)的一種形式。一般說來,在程序設(shè)計(jì)階段所使用的任何方法都可以應(yīng)用到錯(cuò)誤修正的過程中來。 § 修改源代碼程序,不要改變目標(biāo)代碼。 7. 測(cè)試中的可靠性分析在軟件開發(fā)的過程中,利用測(cè)試的統(tǒng)計(jì)數(shù)據(jù),估算軟件的可靠性,以控制軟件的質(zhì)量是至關(guān)重要的。 7.1推測(cè)錯(cuò)誤的產(chǎn)生頻度估算錯(cuò)誤產(chǎn)生頻度的一種方法是估算平均失效等待時(shí)間MTTF(Mean Time To Failure)。MTTF估算公式(Shooman模型)是 ET 是測(cè)試之前程序中原有的故障總數(shù); IT 是程序長度(機(jī)器指令條數(shù)或簡單匯編語句條數(shù)); t是測(cè)試(包括排錯(cuò))的時(shí)間; EC (t) 是在0~t期間內(nèi)檢出并排除的故障總數(shù)。 § 單位元(程序)長度中的故障數(shù)ET∕IT近似為常數(shù),它不因測(cè)試與排錯(cuò)而改變。 統(tǒng)計(jì)數(shù)字表明,通常ET∕IT 值的變化范圍在0.5×10-2~2×10-2之間; § 故障檢出率正比于程序中殘留故障數(shù),而MTTF與程序中殘留故障數(shù)成正比; § 故障不可能完全檢出,但一經(jīng)檢出立即得到改正。 下面對(duì)此問題做一分析: 設(shè)EC (τ) 是0~τ時(shí)間內(nèi)檢出并排除的故障總數(shù),τ是測(cè)試時(shí)間(月),則在同一段時(shí)間0~τ內(nèi)的單條指令累積規(guī)范化排除故障數(shù)曲線εc (τ) 為: 這條曲線在開始呈遞增趨勢(shì),然后逐漸和緩,最后趨近于一水平的漸近線ET∕IT。利用公式的基本假定:故障檢出率(排錯(cuò)率)正比于程序中殘留故障數(shù)及殘留故障數(shù)必須大于零,經(jīng)過推導(dǎo)得:
這就是故障累積的S型曲線模型,參看圖11。 圖11 故障累積曲線與故障檢出曲線
故障檢出曲線服從指數(shù)分布,亦在圖11中顯示。
7.2估算軟件中故障總數(shù)ET的方法①利用Shooman模型估算程序中原來錯(cuò)誤總量ET —瞬間估算
所以, 若設(shè)T是軟件總的運(yùn)行時(shí)間,M是軟件在這段時(shí)間內(nèi)的故障次數(shù),則 T∕M = 1∕λ= MTTF 現(xiàn)在對(duì)程序進(jìn)行兩次不同的互相獨(dú)立的功能測(cè)試,相應(yīng)檢錯(cuò)時(shí)間τ1 <τ2,檢出的錯(cuò)誤數(shù)EC (τ1 ) < EC (τ2 ),則有
且
解上述方程組,得到ET的估計(jì)值和K的估計(jì)值。
② 利用植入故障法估算程序中原有故障總數(shù)ET ─ 捕獲-再捕獲抽樣法 若設(shè)NS是在測(cè)試前人為地向程序中植入的故障數(shù)(稱播種故障),nS是經(jīng)過一段時(shí)間測(cè)試后發(fā)現(xiàn)的播種故障的數(shù)目,nO是在測(cè)試中又發(fā)現(xiàn)的程序原有故障數(shù)。設(shè)測(cè)試用例發(fā)現(xiàn)植入故障和原有故障的能力相同,則程序中原有故障總數(shù)ET的估算值為 在此方法中要求對(duì)播種故障和原有故障同等對(duì)待,因此可以由對(duì)這些植入的已知故障一無所知的測(cè)試專業(yè)小組進(jìn)行測(cè)試。 這種對(duì)播種故障的捕獲─再捕獲的抽樣方法顯然需要消耗許多時(shí)間在發(fā)現(xiàn)和修改播種故障上,這會(huì)影響工程的進(jìn)度,而且要想使植入的故障有利于精確地推測(cè)原有的故障數(shù),如何選擇和植入這些播種故障也是一件很困難的事情。為了回避這些難點(diǎn),就有了下面不必埋設(shè)播種故障的方法。 ③ Hyman分別測(cè)試法 這是對(duì)植入故障法的一種補(bǔ)充。由兩個(gè)測(cè)試員同時(shí)互相獨(dú)立地測(cè)試同一程序的兩個(gè)副本,用t表示測(cè)試時(shí)間(月),記t = 0時(shí),程序中原有故障總數(shù)是B0;t = t1時(shí),測(cè)試員甲發(fā)現(xiàn)的故障總數(shù)是B1;測(cè)試員乙發(fā)現(xiàn)的故障總數(shù)是B2;其中兩人發(fā)現(xiàn)的相同故障數(shù)目是bc;兩人發(fā)現(xiàn)的不同故障數(shù)目是bi。 在大程序測(cè)試時(shí),頭幾個(gè)月所發(fā)現(xiàn)的錯(cuò)誤在總的錯(cuò)誤中具有代表性,兩個(gè)測(cè)試員測(cè)試的結(jié)果應(yīng)當(dāng)比較接近,bi不是很大。這時(shí)有 如果bi比較顯著,應(yīng)當(dāng)每隔一段時(shí)間,由兩個(gè)測(cè)試員再進(jìn)行分別測(cè)試,分析測(cè)試結(jié)果,估算B0。如果bi減小,或幾次估算值的結(jié)果相差不多,則可用B0作為程序中原有錯(cuò)誤總數(shù)ET的估算值。 |
|