白盒測試(White Box Testing),又稱結構測試、邏輯驅動測試或基于程序的測試,是軟件測試的重要方法。它根據軟件產品的內部工作過程,在計算機上進行測試,以證實每種內部操作是否符合設計規格要求,所有內部成分是否已經過檢查。其目的是發現程序編碼過程中的錯誤。
白盒測試從測試重點來看,可以分為控制流分析技術和數據流分析技術。從是否執行程序的角度來看,可分為靜態測試方法和動態測試方法。靜態測試方法主要為程序結構分析法,可分為代碼走查、代碼審查、控制流分析、數據流分析、信息流分析等;動態測試方法主要分為邏輯覆蓋法和路徑測試法等,運用最廣泛的是路徑測試法。
白盒測試的靜態測試工具主要有Logiscope、PRQA軟件等,動態測試工具主要有DevPartner軟件、Pure系列等,可以幫助軟件測試人員增大代碼的覆蓋率,提高代碼的質量,發現代碼中隱藏的問題。
基本概念
白盒測試是在了解產品內部工作的基礎上,通過測試來檢驗產品內部動作是否按照規格說明書的規定進行的。它不管系統的功能,而是按照程序內部的結構測試程序,檢驗每條程序是否都能按照預定要求正常工作。它一般用來分析程序的內部結構,程序的結構和處理過程像白盒子一樣透明,允許測試人員利用程序內部的邏輯結構及有關信息,設計或選擇測試用例,對程序所有邏輯路徑進行測試。白盒測試主要應用于單元測試和集成測試階段,通常不適用于系統測試,但在系統描述中涉及動態描述的部分,仍然可以借鑒一些白盒測試的方法進行測試,因此,白盒測試并不僅限于單元測試和集成測試。
目的與原則
白盒測試的主要目的是對程序模塊進行檢查,檢查過程中需要遵循如下原則:
? 保證程序模塊的所有獨立執行路徑至少測試一遍;
? 對所有的邏輯判定,取“真”與取“假”的兩種情況都能至少測試一遍;
? 在上下邊界及可操作范圍內運行所有循環;
? 檢查程序的內部數據結構,保證其結構的有效性
動態測試方法
動態測試是在程序運行狀態下的測試,即通過輸入預先設計好的數據,根據程序運行計算輸出的結果,將其與實際輸出結果進行比較,進而發現程序中存在的錯誤。在程序的運行過程中,通過動態測試,測試人員可以判斷程序的基本模塊、執行過程、子系統以及整體系統的運行結果是否存在缺陷。動態測試方法一共分為三步,首先設定待測試的配置,然后對相關的源程序進行插樁,編譯連結生成可執行文件,最后運行插樁后的程序系統自動記錄執行路徑,得出覆蓋率。動態測試方法分為邏輯覆蓋法和路徑測試法,其中路徑測試法運用最為廣泛。
邏輯覆蓋法
邏輯覆蓋是對一系列測試的總稱,這種方法要求測試人員對程序的邏輯結構有清楚的理解。根據覆蓋目標不同和覆蓋源程序語句的詳盡程度,常用的邏輯覆蓋可分為語句覆蓋、判定覆蓋、條件覆蓋、判定—條件覆蓋、條件組合覆蓋、路徑覆蓋等六種。
語句覆蓋
語句覆蓋就是設計若干個測試用例,然后運行被測程序,使得每一條可執行語句至少執行一次。這種覆蓋使得程序中每個可執行語句都得到執行,但它是最弱的邏輯覆蓋標準,效果有限,必須與其他方法交互使用。
在上圖案例中,若要使圖中每個語句都執行一次,程序的執行路徑應該是ace,通過a=2,b=3,x=0(x可以是任何數)這一測試數據可以覆蓋該路徑。在這一案例中,兩個判斷條件都只測試了條件為真的情況,如果條件為假時處理有誤,則不能發現。因此該測試是不充分的,語句覆蓋能力較弱,無法發現程序中某些邏輯運算符和邏輯條件的錯誤。
判定覆蓋
判定覆蓋就是設計若干個測試用例,然后運行被測程序,使得程序中每個判斷的取真分支和取假分支至少經歷一次。
對于案例中的被測試模塊流程圖,通過路徑ace和abd,或路徑acd和abe,即可達到判定覆蓋標準。例如,a=3,b=0,x=3便可以覆蓋acd路徑,a=1,b=1,x=1可以覆蓋abe路徑。
判定覆蓋略勝于語句覆蓋,但還不能保證能查出在判斷的條件中存在的錯誤。因此,還需要更強的邏輯覆蓋準則去檢驗判斷內部條件。
條件覆蓋
條件覆蓋就是設計若干個測試用例,然后運行被測程序,使得程序中每個判斷的每個條件的可能取值至少執行一次。
對于案例中的被測試模塊流程圖,共有兩個判定表達式,每個表達式中有兩個條件,為了做到條件覆蓋,應該選取測試數據使得以下四個條件的可能取值至少執行一次:
設計下述兩組測試數據滿足條件覆蓋:
①a=2,b=0,x=4(滿足a>1,b=0;a=2,x>1,執行路徑ace)
②a=1,b=1,x=1(滿足a≤1,b≠0;a≠2,x≤1,執行路徑abe)
條件覆蓋深入到判定中的每個條件,但可能不能滿足判定覆蓋的要求。例如如果使用下面兩組測試數據,則只滿足條件覆蓋標準并不滿足判定覆蓋標準。
①a=2,b=0,x=1(滿足a>1,b=0;a=2,x≤1,執行路徑ace)
②a=1,b=1,x=2(滿足a≤1,b≠0;a≠2,x>1,執行路徑abe)
判定—條件覆蓋
判定-條件覆蓋就是設計足夠的測試用例,使得判斷中每個條件的所有可能取值至少執行一次,同時每個判斷本身的所有可能判斷結果至少執行一次,即要求各個判斷的所有可能的條件取值組合至少執行一次。
對于案例中的被測試模塊流程圖,下面兩組測試數據能達到判定-條件覆蓋標準:
①a=2,b=0,x=4(滿足x>1,b=0;a=2,x>1)
②a=1,b=1,x=1(滿足a≤1,b≠0;a≠2,x≤1)
判定-條件覆蓋也是有缺陷的。從表面上來看,它測試了所有條件的取值,但某些條件掩蓋了另一些條件,會遺漏某些條件取值錯誤的情況。
條件組合覆蓋
多重條件覆蓋就是設計足夠的測試用例,運行被測程序,使得每個判斷的所有可能的條件取值組合至少執行一次。
對于案例中被測模塊流程圖中的條件組合:
下面的4組測試數據可以使上面列出的8種組合至少出現一次:
①a=2,b=0,x=3(針對①和⑤兩種組合,執行路徑ace);
②a=2,b=1,x=1(針對②和⑥兩種組合,執行路徑abe);
③a=1,b=0,x=3(針對③和⑦兩種組合,執行路徑abe);
④a=1,b=1,x=1(針對④和⑧兩種組合,執行路徑abd)。
條件組合是一種比較強的覆蓋準則,可以有效地檢查各種可能的條件取值的組合是否正確。它不但可覆蓋所有條件的可能取值的組合,還可覆蓋所有判斷的可取分支,但可能有的路徑還是會遺漏掉,測試還不完全。
路徑覆蓋
路徑覆蓋,就是設計足夠多的測試用例,執行程序所有可能的路徑,這是覆蓋率最高的一種覆蓋技術。
根據上方案例圖,通過路徑abd,abe,acd,ace,即可達到路徑覆蓋標準。例如,x=4,y=-3,z=2便可以覆蓋ace路徑,x=-1,y=1,z=-1可以覆蓋abd路徑。但是,由于路徑覆蓋需要對所有可能的路徑進行測試(包括循環、條件組合、分支選擇等),因此需要設計大量且復雜的測試用例,從而使工作量呈指數級增長。
Z路徑覆蓋
路徑覆蓋由于路徑數量過多,使用起來多有不便,人們便舍掉了路徑覆蓋的一些次要因素,對循環機制進行簡化,極大地減少了路徑的數量,使得覆蓋這些有限路徑成為可能,這種覆蓋方法稱為Z路徑覆蓋。循環化簡指的是限制循環的次數,只考慮循環執行一次和零次兩種情況,經過Z路徑覆蓋法對程序中循環的簡化后,程序中只存在兩種結構:順序結構和分支結構。
邏輯覆蓋標準對比
路徑測試法
白盒測試有兩種常用技術,一種是覆蓋測試,另一種是路徑測試。從流程圖上講,程序的一次執行對應著從入口到出口的一條路徑,針對路徑的測試即為路徑測試。從廣義的角度講,任何有關路徑分析的測試都可以被稱為路徑測試。路徑測試是在程序控制流圖的基礎上,通過分析控制構造的環路復雜性,導出基本可執行路徑集合,從而設計測試用例。
程序路徑表達
在對路徑進行分析的時候,首先要解決的是確定每個路徑以及路徑數目。為了更加直觀和形象地表達出每條路徑對于某條路徑,可采用弧序列或者節點序列的方式并引了兩個運算:加和乘。弧a和弧b相加,表示為a+b,它表明兩條弧是“或”的關系,是并行的路徑;弧a和弧b相乘,表示為ab,它表明路徑是先經歷弧a,接著再經歷弧b,弧a和弧b是先后相接的。
路徑表達式運算滿足以下規律:
程序的環路復雜性
環路復雜性V(G)的計算方式有以下三種:
基路徑測試
如果把覆蓋的路徑數壓縮到一定限度內,就成為基路徑測試。基路徑測試是在程序控制流圖的基礎上,通過分析控制構造的環路復雜性,導出基本可執行路徑集合,從而設計測試用例的方法。設計出的測試用例要保證在測試中,程序的每一條可執行路徑至少要執行一次。基路徑測試法包括以下五個方面:
1.根據詳細設計或者程序源代碼,繪制出程序的程序流程圖;
2.根據程序流程圖,繪制出程序的控制流圖;
3.計算程序的環路復雜性。環路復雜性是一種為程序邏輯復雜性提供定量測試的軟件度量,將該度量用于計算程序的基本獨立路徑數目;
4.找出獨立路徑。通過程序的程序流程圖導出基本路徑集,列出程序的獨立路徑;
5.設計測試用例。根據程序結構和程序環路復雜性設計用例輸入數據和預期結果,確保基本路徑集中的每一條路徑的執行。
每個測試用例執行之后,與預期結果進行比較,如果所有的測試用例都執行完畢,則可以確信程序中所有的可執行語句至少被執行了一次。但一些獨立的路徑往往不是完全孤立的,有時它是程序正常的控制流的一部分,那這些路徑的測試可以是另一條路徑測試的一部分。
循環測試
循環測試專用于測試程序中的循環,并且可以進一步提高測試覆蓋率。從本質上來說,循環測試的目的就是檢查循環結構的有效性。通常,循環可以劃分為簡單循環、嵌套循環、連鎖循環和非結構循環。
靜態測試方法
靜態測試方法主要為程序結構分析法,可分為代碼審查、代碼走查、控制流分析、數據流分析、信息流分析等。
代碼審查
代碼審查是由若干程序員和測試人員組成審查小組,通過閱讀、討論和爭議,對程序進行靜態分析的過程。代碼審查分兩步:第一步,小組負責人提前把設計規格說明書、控制流程圖、程序文本及有關要求、規范等分發給小組成員,作為審查的依據。小組成員在充分閱讀這些材料后進行審查的第二步,召開程序審查會。在會上,首先由程序員講解程序的邏輯,程序員及其他小組成員可以提出問題,展開討論,審查錯誤是否存在。例如,在某個局部性小問題修改方法的討論,可能發現與之牽連的其他問題,甚至設計模塊的功能說明、模塊間接口和系統總體結構的大問題,從而導致對需求的重定義、重設計、重驗證,進而大大改善了軟件質量。
代碼走查
代碼走查與代碼審查基本相同,其過程分為兩步。第一步也是把材料先發給走查小組每個成員,認真研學后再開會。開會審查的過程與代碼審查不同,不是簡單地讀程序和對照錯誤檢查表進行檢查,而是讓與會者充當計算機,即首先由測試組成員為所測程序準備一批有代表性的測試用例,提交給走查小組。走查小組開會,集體充當計算機的角色,讓測試用例按程序邏輯運行一遍,隨時記錄程序的蹤跡,供分析和討論用。
控制流分析
控制流分析指的是檢查程序的控制結構,以驗證程序結構的一些規則在程序編寫過程中是否得到遵循,在此基礎上得到有關結構成分的語法樹并揭示控制結構的缺陷。對于控制流關系的圖被稱為控制流圖,圖上的每個節點對應一個程序元素,兩個節點間一個直接的弧,表示相應的兩個元素再控制流關系中組成一個順序對。控制流圖中的一條路徑對應于一個潛在可執行的程序元素順序。執行一條路徑就是執行對應的程序元素序列。如果一個輸入引起一條路徑的執行,那么這條路徑就是可達的,否則就是不可達的。通常,含循環的路徑有無線多條,即使沒有循環,一個程序也可能有非常多的路徑需要分析。它有線性結構、基本的條件判斷、多分支的條件判斷、while-do循環、do-while循環五種基本程序結構。控制流分析主要從三個方面來分析程序結構:條件判定節點本身的復雜性;條件判定節點與循環節點對執行路徑產生的影響;循環本身的復雜性。
數據流分析
數據流分析最初是隨著編譯系統生成有效的目標代碼而出現的,這類方法主要用于優化代碼。數據流測試是基于程序的控制流,從建立的數據目標狀態的序列中發現異常的結構測試方法。其基本思想是一個變量的定義,通過輾轉的引用和定義,可以影響到另一個變量的值,或者影響到路徑的選擇等。進行數據流測試時,根據被測試程序中的變量的定義和引用位置選擇測試路徑。主要遵循以下覆蓋準則:
信息流分析
信息流分析主要用于驗證程序變量間信息的傳輸是否遵循保密要求,通過對輸入數據、輸出數據、語句之間的關系的分析來檢查程序錯誤。信息流分析主要用于分析是否存在無用的語句。信息流分析能夠列出對輸入變量的所有可能的引用,在程序的任何指定點檢查其執行是否影響某一輸出變量值的語句,為輸入輸出關系提供一種檢查,看每個輸出值是否由相應的輸入值導出。
其他測試方法
程序插裝
程序插裝使被測程序在保持原有邏輯完整性基礎上,在程序中插入一些探針,通過探針的執行,拋出程序的運行特征數據。基于這些特征數據分析,可以獲得程序的控制流及數據流信息,進而得到邏輯覆蓋等動態信息。程序中什么部位設置探針、如何設計探針以及探針函數捕獲數據的編碼和解碼。
程序插裝在實踐中應用廣泛,可以用來捕獲程序執行過程中變量值的變化情況,也可以用來檢測程序的分支覆蓋和語句覆蓋。程序插裝的關鍵技術包括要探測哪些信息、在程序中什么部位設置探針、如何設計探針以及探針函數捕獲數據的編碼和解碼。
域測試
域測試的“域”是指程序的輸入空間,域測試方法基于對輸入空間的分析,其理想結果就是檢驗輸入空間中的每一個輸入元素是否都產生正確結果。而輸入空間又可以分為不同的子空間,每一子空間對應一種不同的計算。在考察被測試程序的結構后發現,子空間的劃分是由程序中分支語句的謂詞決定,輸入空間的一個元素,經過程序中某些特定語句的執行而結束。域測試正是在分析輸入域的基礎上,選擇恰當的測試點后進行測試的。
符號測試
符號測試沿用傳統的程序測試方法,通過運行被測試程序來驗證它的可靠性。此外,由于一次符號測試的結果代表了一大類普通測試的運行結果,實際上是證明程序接受此類輸入,所得輸出結果是否正確。從符號測試的使用方法來看,問題的關鍵在于開發出比傳統的編譯器功能更強。能夠處理符號運算的編譯器和解釋器。
程序變異
程序變異測試是一種錯誤驅動測試,它針對某類特定程序錯誤。因為人們無法查找出程序中的所有錯誤,所以比較現實的方法是將錯誤的范圍盡可能地縮小,以利于專門測試某類錯誤是否存在。這樣便于把目標集中于對軟件危害最大的可能錯誤,取得較高的測試效率,并降低測試成本。
測試覆蓋準則
測試覆蓋準則有K.A.Foster的ESTCA覆蓋準則和Woodward等人的層次LCSAJ覆蓋準則。Foster的經驗型覆蓋準則是從硬件的早期測試方法中得到啟發的,通過大量的實驗確定了程序中謂詞最容易出錯的部分,得出了一套錯誤敏感測試用例分析ESTCA(Error Sensitive Test Cases Analysis)規則。Woodward等人提出了一種層次LCSAJ覆蓋準則,LCSAJ (Linear Code Sequence and Jump)的意思是線性代碼序列與跳轉,一個LCSAJ是一組順序執行的代碼,以控制流跳轉為其結束點,它表明越是高層的覆蓋準則越難滿足。
ESTCA覆蓋準則
ESTCA覆蓋準則也叫錯誤敏感測試用例分析規則,是根據程序中的謂詞最容易出錯的部分得出的規則,屬于大數據的范疇。ESTCA覆蓋準則針對程序編寫人員容易發生的錯誤,或是圍繞著發生錯誤的頻繁區域,從而提高發現錯誤的概率,它具有三點規則。
規則一:對于A rel B(rel可以是<、=和>)型的分支謂詞,應適當選擇A與B的值,使得測試執行到該分支語句時,A<B、A=B和A>B的情況分別出現一次。
規則二:對于A rel1 C(rel1可以是>或<,A是變量,C是常量)型的分支謂詞,當rel1為<時,應適當選擇A的值,使A=C-M。(M是距C最小的容器允許的正數,若A和C均為整型,則M=1)。同樣,當rel1為>時,應適當選擇A的值,使A=C+M。
規則三:對外部輸入變量賦值,使其在每一測試用例中均有不同的值和符號,并與同一組測試用例中其他變量的值和符號不一致。
LCSAJ覆蓋準則
LCSAJ覆蓋準則也叫線性代碼序列與跳轉,一個LCSAJ是一組順序執行的代碼,以控制流跳轉為其結束點,LCSAJ的起點是程序第一行或轉移語句的入口點或控制流可以到達的點,幾個首尾相連,最后一個LCSAJ終點為程序終點的LCSAJ串組成程序的一條路徑。LCSAJ覆蓋準則是一個分層覆蓋準則:
第一層用語句覆蓋;
第二層是分支覆蓋;
第三層是一段LCSAJ覆蓋,即程序的每一個LCSAJ都至少在測試中經歷一次;
第四層就是任意相連的兩段LCSAJ覆蓋,即程序中每兩個首尾相連的LCSAJ組合起來在測試中都要經歷一次;
第五層就是任意相連的三層LCSAJ覆蓋;
第n+2層就是每n個首尾相連的LCSAJ組合在測試中都要經歷一次,以此類推。
測試方法選擇
白盒測試中測試方法的選擇策略如下:
1.在測試時,首先進行靜態結構分析。
2.采用先靜態后動態的組合方式,在進行靜態結構分析、代碼檢查和靜態質量度量后,再進行覆蓋測試。
3.利用靜態分析的結果,通過代碼檢查和動態測試的方法對結果做進一步確認,使測試工作更為有效。
4.覆蓋率測試是白盒測試的重點,使用基路徑測試達到語句覆蓋標準,對于重點模塊,應使用多種覆蓋標準衡量代碼的覆蓋率。
5.不同的測試階段,側重點不同。
測試工具
適用范圍
白盒測試適用于單元測試、集成測試和回歸測試。單元測試指的是檢查和驗證軟件中的最小可測試單元,單元是一個軟件組件,不能再細分為其他組件,軟件工程師編寫白盒測試用例來檢查單元編碼是否正確。
集成測試將軟件組件、硬件組件或兩者結合起來進行測試,以評估它們之間的交互作用。測試人員可以編寫白盒測試用例和黑盒測試用例來明確檢查各種單元之間的接口。
回歸測試,即對系統或組件進行選擇性重新測試,以驗證修改不會造成意外影響,并且系統或組件仍符合其規定要求。回歸測試可以通過黑盒測試用例、白盒測試用例或兩者的組合來完成,白盒測試和集成測試用例可以作為回歸測試的一部分保存并允許。
與黑盒測試對比
參考資料 >
第三章 白盒測試.bookshow.2024-03-06
【基礎理論-白盒測試】.阿里云開發者社區.2024-03-06
PRQA官網.PRQA.2024-03-02
WhiteBox.pdf.chaudhary..2024-03-06