深入淺出單元測試[3] 單元測試工具
下面談談測試用例設計。前面已經說了,測試用例的核心是輸入數據。預期輸出是依據輸入數據和程序功能來確定的,也就是說,對于某一程序,輸入數據確定了,預期輸出也就可以確定了,至于生成/銷毀被測試對象和運行測試的語句,是所有測試用例都大同小異的,因此,我們討論測試用例時,只討論輸入數據。
前面說過,輸入數據包括四類:參數、成員變量、全局變量、IO媒體,這四類數據中,只要所測試的程序需要執行讀操作的,就要設定其初始值,其中,前兩類比較常用,后兩類較少用。顯然,把輸入數據的所有可能取值都進行測試,是不可能也是無意義的,我們應該用一定的規則選擇有代表性的數據作為輸入數據,主要有三種:正常輸入,邊界輸入,非法輸入,每種輸入還可以分類,也就是平常說的等價類法,每類取一個數據作為輸入數據,如果測試通過,可以肯定同類的其他輸入也是可以通過的。下面舉例說明:
正常輸入
例如字符串的Trim函數,功能是將字符串前后的空格去除,那么正常的輸入可以有四類:前面有空格;后面有空格;前后均有空格;前后均無空格。
邊界輸入
上例中空字符串可以看作是邊界輸入。
再如一個表示年齡的參數,它的有效范圍是0-100,那么邊界輸入有兩個:0和100。
非法輸入
非法輸入是正常取值范圍以外的數據,或使代碼不能完成正常功能的輸入,如上例中表示年齡的參數,小于0或大于100都是非法輸入,再如一個進行文件操作的函數,非法輸入有這么幾類:文件不存在;目錄不存在;文件正在被其他程序打開;權限錯誤。
如果函數使用了外部數據,則正常輸入是肯定會有的,而邊界輸入和非法輸入不是所有函數都有。一般情況下,即使沒有設計文檔,考慮以上三種輸入也可以找出函數的基本功能點。實際上,單元測試與代碼編寫是“一體兩面”的關系,編碼時對上述三種輸入都是必須考慮的,否則代碼的鍵壯性就會成問題。
四 白盒覆蓋
上面所說的測試數據都是針對程序的功能來設計的,就是所謂的黑盒測試,另外,單元測試還需要從另一個角度來設計測試數據,即針對程序的邏輯結構來設計測試用例,就是所謂的白盒測試。在老納看來,如果黑盒測試是足夠充分的,那么白盒測試就沒有必要,可惜“足夠充分”只是一種理想狀態,例如:真的是所有功能點都測試了嗎?程序的功能點是人為的定義,常常是不全面的;各個輸入數據之間,有些組合可能會產生問題,怎樣保證這些組合都經過了測試?難于衡量測試的完整性是黑盒測試的主要缺陷,而白盒測試恰恰具有易于衡量測試完整性的優點,兩者之間具有極好的互補性,例如:完成功能測試后統計語句覆蓋率,如果語句覆蓋未完成,很可能是未覆蓋的語句所對應的功能點未測試。
白盒測試針對程序的邏輯結構設計測試用例,用邏輯覆蓋率來衡量測試的完整性。邏輯單位主要有:語句、分支、條件、條件值、條件值組合,路徑。語句覆蓋就是覆蓋所有的語句,其他類推。另外還有一種判定條件覆蓋,其實是分支覆蓋與條件覆蓋的組合,在此不作討論。跟條件有關的覆蓋就有三種,解釋一下:條件覆蓋是指覆蓋所有的條件表達式,即所有的條件表達式都計算了,不考慮計算結果;條件值覆蓋是指覆蓋條件的所有可能取值,即每個條件的取真值和取假值都要計算一次;條件值組合覆蓋是指覆蓋所有條件取值的所有可能組合。老納做過一些粗淺的研究,發現與條件直接有關的錯誤主要是邏輯操作符錯誤,例如:||寫成&&,漏了寫!什么的,采用分支覆蓋與條件覆蓋的組合,基本上可以發現這些錯誤,另一方面,條件值覆蓋與條件值組合覆蓋往往需要大量的測試用例,因此,在老納看來,條件值覆蓋和條件值組合覆蓋的效費比偏低。老納認為效費比較高且完整性也足夠的測試要求是這樣的:完成功能測試,完成語句覆蓋、條件覆蓋、分支覆蓋、路徑覆蓋。做過單元測試的朋友恐怕會對老納提出的測試要求給予一個字的評價:暈!或者兩個字的評價:狂暈!因為這似乎是不可能的要求,要達到這種測試完整性,其測試成本是不可想象的,不過,出家人不打逛語,老納之所以提出這種測試要求,是因為利用一些工具,可以在較低的成本下達到這種測試要求,后面將會作進一步介紹。
文章來源于領測軟件測試網 http://www.kjueaiud.com/