我們一直強(qiáng)調(diào)單元測試的重要性,但是有一個(gè)問題可能沒有認(rèn)真去想過,測試是重要的,但是我們測試什么呢?最近重讀《單元測試之道》,書中給出了答案:Right-BICEP
1.Right——正確
很顯然,如果代碼運(yùn)行的結(jié)果與你預(yù)期的不符合,那么這段代碼肯定是有問題的。需要注意的是,Right并意味著正確,因?yàn)檎_只是相對你所期望的結(jié)果而言,而對于用戶需求也許就是錯(cuò)誤的。
2.B——邊界條件
尋找邊界條件是單元測試最有價(jià)值的工作之一,因?yàn)閎ug一般出現(xiàn)在邊界條件上,你常常需要考慮下面這些邊界條件:
1)完全偽造或者不一直的數(shù)據(jù)進(jìn)行輸入
2)格式錯(cuò)誤的數(shù)據(jù),比如錯(cuò)誤的URL,Email地址
3)空值或者不完整值,比如0,null
4)與常理相去甚遠(yuǎn)的數(shù)據(jù),比如人有10000歲?
5)如果要求傳入的是一個(gè)不允許重復(fù)數(shù)據(jù)的list,你傳入一個(gè)有重復(fù)數(shù)據(jù)的看看出現(xiàn)什么情況
6)如果需要傳入的有序的集合,你傳入一個(gè)無序的看看結(jié)果
7)不按照次序地執(zhí)行,比如未登錄就嘗試操作某功能等
對于邊界條件,可以按照CORRECT的順序去嘗試:
Conformance——一致性,值是否和預(yù)期的一樣
Ordering——順序性,值是否如預(yù)期的那樣,有序或者無序
Range——區(qū)間性,值是否處于合理的范圍內(nèi)
Reference——引用,值是否引用了代碼無法空值的外部資源
Existence——值是否存在,為空?為0?不在集合內(nèi)?
Cardinatity——基數(shù)性,檢查你的函數(shù)能否正確地計(jì)數(shù),不多不少
Time——所有的事件的發(fā)生是否按照預(yù)期的順序,性能上滿足要求?
3.Inverse——檢查反向引用
如果方法導(dǎo)致某個(gè)結(jié)果,嘗試以另一個(gè)方法能否返回最初的狀態(tài)?與原狀態(tài)是否符合預(yù)期?
4。Cross——交叉檢查
通過不同的方法檢查一個(gè)方法產(chǎn)生的結(jié)果是否正確,比如用Math.sqrt方法檢查自己編寫的求平方根的方法是否正確。另外的方式,以一種數(shù)量去檢查另一種數(shù)量,比如圖書館借出的書加上架上的書的總數(shù)是固定,可以用借出的書來檢查架上的書的數(shù)量是否正確。
5.E——強(qiáng)制錯(cuò)誤條件的產(chǎn)生
一般我們所能想到的環(huán)境因素:
1)內(nèi)存耗光
2)磁盤用滿
3)時(shí)鐘出問題
4)網(wǎng)絡(luò)不可用或者有問題
5)系統(tǒng)過載
6)調(diào)色板顏色數(shù)目有限
7)顯示分辨率過高
再比如JDK版本差異,我就為這個(gè)問題頭痛過:)
6.Performance——性能
每天或者每隔幾天運(yùn)行一下一個(gè)粗糙簡單的性能測試,能夠保證你不會在給用戶演示的時(shí)候出現(xiàn)尷尬的場面。
盡管書上是講了這么多測試這個(gè)、測試那個(gè),我想真實(shí)的項(xiàng)目場景中應(yīng)該根據(jù)需要采取特定的測試策略,比如你總不能對于一個(gè)單機(jī)應(yīng)用需要考慮地震震斷海底光纜引發(fā)的問題。就我自己而言,因?yàn)轫?xiàng)目組中似乎只有我對JUnit等單元測試工具充滿興趣,有經(jīng)驗(yàn)的老程序員是自己寫一個(gè)帶Main方法的Test類進(jìn)行測試,而更多的人根本就不知道單元測試或者知道也不感興趣,在沒有壓力的情況下,要求自己考慮這么多的測試內(nèi)容,難矣。今天試用了下NUnit,感覺比JUnit難用多了,JUnit與Eclipse的結(jié)合非常簡便。
1.Right——正確
很顯然,如果代碼運(yùn)行的結(jié)果與你預(yù)期的不符合,那么這段代碼肯定是有問題的。需要注意的是,Right并意味著正確,因?yàn)檎_只是相對你所期望的結(jié)果而言,而對于用戶需求也許就是錯(cuò)誤的。
2.B——邊界條件
尋找邊界條件是單元測試最有價(jià)值的工作之一,因?yàn)閎ug一般出現(xiàn)在邊界條件上,你常常需要考慮下面這些邊界條件:
1)完全偽造或者不一直的數(shù)據(jù)進(jìn)行輸入
2)格式錯(cuò)誤的數(shù)據(jù),比如錯(cuò)誤的URL,Email地址
3)空值或者不完整值,比如0,null
4)與常理相去甚遠(yuǎn)的數(shù)據(jù),比如人有10000歲?
5)如果要求傳入的是一個(gè)不允許重復(fù)數(shù)據(jù)的list,你傳入一個(gè)有重復(fù)數(shù)據(jù)的看看出現(xiàn)什么情況
6)如果需要傳入的有序的集合,你傳入一個(gè)無序的看看結(jié)果
7)不按照次序地執(zhí)行,比如未登錄就嘗試操作某功能等
對于邊界條件,可以按照CORRECT的順序去嘗試:
Conformance——一致性,值是否和預(yù)期的一樣
Ordering——順序性,值是否如預(yù)期的那樣,有序或者無序
Range——區(qū)間性,值是否處于合理的范圍內(nèi)
Reference——引用,值是否引用了代碼無法空值的外部資源
Existence——值是否存在,為空?為0?不在集合內(nèi)?
Cardinatity——基數(shù)性,檢查你的函數(shù)能否正確地計(jì)數(shù),不多不少
Time——所有的事件的發(fā)生是否按照預(yù)期的順序,性能上滿足要求?
3.Inverse——檢查反向引用
如果方法導(dǎo)致某個(gè)結(jié)果,嘗試以另一個(gè)方法能否返回最初的狀態(tài)?與原狀態(tài)是否符合預(yù)期?
4。Cross——交叉檢查
通過不同的方法檢查一個(gè)方法產(chǎn)生的結(jié)果是否正確,比如用Math.sqrt方法檢查自己編寫的求平方根的方法是否正確。另外的方式,以一種數(shù)量去檢查另一種數(shù)量,比如圖書館借出的書加上架上的書的總數(shù)是固定,可以用借出的書來檢查架上的書的數(shù)量是否正確。
5.E——強(qiáng)制錯(cuò)誤條件的產(chǎn)生
一般我們所能想到的環(huán)境因素:
1)內(nèi)存耗光
2)磁盤用滿
3)時(shí)鐘出問題
4)網(wǎng)絡(luò)不可用或者有問題
5)系統(tǒng)過載
6)調(diào)色板顏色數(shù)目有限
7)顯示分辨率過高
再比如JDK版本差異,我就為這個(gè)問題頭痛過:)
6.Performance——性能
每天或者每隔幾天運(yùn)行一下一個(gè)粗糙簡單的性能測試,能夠保證你不會在給用戶演示的時(shí)候出現(xiàn)尷尬的場面。
盡管書上是講了這么多測試這個(gè)、測試那個(gè),我想真實(shí)的項(xiàng)目場景中應(yīng)該根據(jù)需要采取特定的測試策略,比如你總不能對于一個(gè)單機(jī)應(yīng)用需要考慮地震震斷海底光纜引發(fā)的問題。就我自己而言,因?yàn)轫?xiàng)目組中似乎只有我對JUnit等單元測試工具充滿興趣,有經(jīng)驗(yàn)的老程序員是自己寫一個(gè)帶Main方法的Test類進(jìn)行測試,而更多的人根本就不知道單元測試或者知道也不感興趣,在沒有壓力的情況下,要求自己考慮這么多的測試內(nèi)容,難矣。今天試用了下NUnit,感覺比JUnit難用多了,JUnit與Eclipse的結(jié)合非常簡便。