您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 >
用Cobertura做測(cè)試覆蓋率
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/1/28 13:59:40 ] 推薦標(biāo)簽:

圖 3. NameFunction 類(lèi)中的代碼覆蓋率

Cobertura 是 jcoverage 的分支(請(qǐng)參閱 參考資料)。GPL 版本的 jcoverage 已經(jīng)有一年沒(méi)有更新過(guò)了,并且有一些長(zhǎng)期存在的 bug,Cobertura 修復(fù)了這些 bug。原來(lái)的那些 jcoverage 開(kāi)發(fā)人員不再繼續(xù)開(kāi)發(fā)開(kāi)放源碼,他們轉(zhuǎn)向開(kāi)發(fā) jcoverage 的商業(yè)版和 jcoverage+,jcoverage+ 是一個(gè)從同一代碼基礎(chǔ)中發(fā)展出來(lái)的封閉源代碼產(chǎn)品。開(kāi)放源碼的奇妙之處在于:一個(gè)產(chǎn)品不會(huì)因?yàn)樵_(kāi)發(fā)人員決定讓他們的工作獲得相應(yīng)的報(bào)酬而消亡。

確認(rèn)遺漏的測(cè)試

利用 Cobertura 報(bào)告,可以找出代碼中未測(cè)試的部分并針對(duì)它們編寫(xiě)測(cè)試。例如,圖 3 顯示 Jaxen 需要進(jìn)行一些測(cè)試,運(yùn)用 name() 函數(shù)對(duì)文字節(jié)點(diǎn)、注釋節(jié)點(diǎn)、處理指令節(jié)點(diǎn)、屬性節(jié)點(diǎn)和名稱空間節(jié)點(diǎn)進(jìn)行測(cè)試。

如果有許多未覆蓋的代碼,像 Cobertura 在這里報(bào)告的那樣,那么添加所有缺少的測(cè)試將會(huì)非常耗時(shí),但也是值得的。不一定要一次完成它。您可以從被測(cè)試的少的代碼開(kāi)始,比如那些所有沒(méi)有覆蓋的包。在測(cè)試所有的包之后,可以對(duì)每一個(gè)顯示為沒(méi)有覆蓋的類(lèi)編寫(xiě)一些測(cè)試代碼。對(duì)所有類(lèi)進(jìn)行專(zhuān)門(mén)測(cè)試后,還要為所有未覆蓋的方法編寫(xiě)測(cè)試代碼。在測(cè)試所有方法之后,可以開(kāi)始分析對(duì)未測(cè)試的語(yǔ)句進(jìn)行測(cè)試的必要性。

(幾乎)不留下任何未測(cè)試的代碼

是否有一些可以測(cè)試但不應(yīng)測(cè)試的內(nèi)容?這取決于您問(wèn)的是誰(shuí)。在 JUnit FAQ 中,J. B. Rainsberger 寫(xiě)到“一般的看法是:如果 自身 不會(huì)出問(wèn)題,那么它會(huì)因?yàn)樘?jiǎn)單而不會(huì)出問(wèn)題。第一個(gè)例子是 getX() 方法。假定 getX() 方法只提供某一實(shí)例變量的值。在這種情況下,除非編譯器或者解釋器出了問(wèn)題,否則 getX() 是不會(huì)出問(wèn)題的。因此,不用測(cè)試 getX(),測(cè)試它不會(huì)帶來(lái)任何好處。對(duì)于 setX() 方法來(lái)說(shuō)也是如此,不過(guò),如果 setX() 方法確實(shí)要進(jìn)行任何參數(shù)驗(yàn)證,或者說(shuō)確實(shí)有副作用,那么還是有必要對(duì)其進(jìn)行測(cè)試。”
 

理論上,對(duì)未覆蓋的代碼編寫(xiě)測(cè)試代碼不一定會(huì)發(fā)現(xiàn) bug。但在實(shí)踐中,我從來(lái)沒(méi)有碰到?jīng)]有發(fā)現(xiàn) bug 的情況。未測(cè)試的代碼充滿了 bug。所做的測(cè)試越少,在代碼中隱藏的、未發(fā)現(xiàn)的 bug 會(huì)越多。

我不同意。我已經(jīng)記不清在“簡(jiǎn)單得不會(huì)出問(wèn)題”的代碼中發(fā)現(xiàn)的 bug 的數(shù)量了。確實(shí),一些 getter 和 setter 很簡(jiǎn)單,不可能出問(wèn)題。但是我從來(lái)沒(méi)有辦法區(qū)分哪些方法是真的簡(jiǎn)單得不會(huì)出錯(cuò),哪些方法只是看上去如此。編寫(xiě)覆蓋像 setter 和 getter 這樣簡(jiǎn)單方法的測(cè)試代碼并不難。為此所花的少量時(shí)間會(huì)因?yàn)樵谶@些方法中發(fā)現(xiàn)未曾預(yù)料到的 bug 而得到補(bǔ)償。

一般來(lái)說(shuō),開(kāi)始測(cè)量后,達(dá)到 90% 的測(cè)試覆蓋率是很容易的。將覆蓋率提高到 95% 或者更高需要?jiǎng)右幌履X筋。例如,可能需要裝載不同版本的支持庫(kù),以測(cè)試沒(méi)有在所有版本的庫(kù)中出現(xiàn)的 bug;蛘咝枰匦聵(gòu)建代碼,以便測(cè)試通常執(zhí)行不到的部分代碼。可以對(duì)類(lèi)進(jìn)行擴(kuò)展,讓它們的受保護(hù)方法變?yōu)楣卜椒,這樣可以對(duì)這些方法進(jìn)行測(cè)試。這些技巧看起來(lái)像是多此一舉,但是它們?cè)鴰椭以谝话氲臅r(shí)間內(nèi)發(fā)現(xiàn)更多的未發(fā)現(xiàn)的 bug。

并不總是可以得到完美的、 的代碼覆蓋率。有時(shí)您會(huì)發(fā)現(xiàn),不管對(duì)代碼如何改造,仍然有一些行、方法、甚至是整個(gè)類(lèi)是測(cè)試不到的。下面是您可能會(huì)遇到的挑戰(zhàn)的一些例子:

    只在特定平臺(tái)上執(zhí)行的代碼。例如,在一個(gè)設(shè)計(jì)良好的 GUI 應(yīng)用程序中,添加一個(gè) Exit 菜單項(xiàng)的代碼可以在 Windows PC 上運(yùn)行,但它不能在 Mac 機(jī)上運(yùn)行。

    捕獲不會(huì)發(fā)生的異常的 catch 語(yǔ)句,比如在從 ByteArrayInputStream 進(jìn)行讀取操作時(shí)拋出的 IOException。

    非公共類(lèi)中的一些方法,它們永遠(yuǎn)也不會(huì)被實(shí)際調(diào)用,只是為了滿足某個(gè)接口契約而必須實(shí)現(xiàn)。

    處理虛擬機(jī) bug 的代碼塊,比如說(shuō),不能識(shí)別 UTF-8 編碼。

考慮到上面這些以及類(lèi)似的情況,我認(rèn)為一些極限程序員自動(dòng)刪除所有未測(cè)試代碼的做法是不切實(shí)際的,并且可能具有一定的諷刺性。不能總是獲得完美的測(cè)試覆蓋率并不意味著不會(huì)有更好的覆蓋率。

然而,比執(zhí)行不到的語(yǔ)句和方法更常見(jiàn)的是殘留代碼,它不再有任何作用,并且從代碼基中去掉這些代碼也不會(huì)產(chǎn)生任何影響。有時(shí)可以通過(guò)使用反射來(lái)訪問(wèn)私有成員這樣的怪招來(lái)測(cè)試未測(cè)試的代碼。還可以為未測(cè)試的、包保護(hù)(package-protected)的代碼來(lái)編寫(xiě)測(cè)試代碼,將測(cè)試類(lèi)放到將要測(cè)試的類(lèi)所在那個(gè)包中。但好不要這樣做。所有不能通過(guò)發(fā)布的(公共的和受保護(hù)的)接口訪問(wèn)的代碼都應(yīng)刪除。執(zhí)行不到的代碼不應(yīng)當(dāng)成為代碼基的一部分。代碼基越小,它越容易被理解和維護(hù)。

上一頁(yè)123下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd