原創|使用教程|編輯:鄭恭琳|2021-01-07 11:05:38.350|閱讀 527 次
概述:如果代碼覆蓋率對您來說是個問題,請確保您對其進行了正確測量,并從您運行的所有測試中對其進行了測量。利用自動JUnit代碼覆蓋率測試用例生成來快速構建和擴展測試,以獲得有意義的、可維護的完整代碼覆蓋率。單元測試覆蓋率是確保您正確測量所有內容的好方法。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
如果代碼覆蓋率對您來說是個問題,請確保您對其進行了正確測量,并從您運行的所有測試中對其進行了測量。利用自動JUnit代碼覆蓋率測試用例生成來快速構建和擴展測試,以獲得有意義的、可維護的完整代碼覆蓋率。單元測試覆蓋率是確保您正確測量所有內容的好方法。
我最近寫了一篇關于陷入代碼覆蓋率百分比陷阱的討論,這引發了質量討論,所以我想我將更深入地探討代碼覆蓋率問題和解決方案。具體來說,涵蓋率本身,自動生成的JUnit測試的值以及如何識別有問題的單元測試。以及如何在執行方面繼續做得更好。
讓我們從覆蓋率指標本身以及我們如何計算代碼覆蓋率開始。代碼覆蓋率數字通常是無意義的,或充其量是誤導的。如果您“確實”擁有100%的代碼覆蓋率,那又意味著什么?您是如何測量的?
有很多不同的方法來衡量覆蓋率。
衡量代碼覆蓋率的一種方法是從需求角度出發。您是否對每一項要求都進行了測試?這是一個合理的開始……但這并不意味著所有代碼都已經過測試。
衡量代碼覆蓋率的另一種方法(別笑,我實際上是在現實世界中聽到的)是通過測試的次數。真的,我是真的!這是一個非常糟糕的指標,顯然毫無意義。是比簡單地計算您擁有多少個測試還差?我不能說。
然后我們來嘗試確定執行了什么代碼。常見的覆蓋率指標包括語句覆蓋率、行覆蓋率、分支覆蓋率、決策覆蓋率、多個條件覆蓋率,或者更全面的MC/DC或修改后的條件/決策覆蓋率。
當然,最簡單的方法是線路覆蓋率,但是您可能已經看到,工具對此進行了不同的衡量,因此覆蓋率將有所不同。執行代碼行并不意味著您已經檢查了該代碼行中可能發生的所有不同情況。這就是為什么安全關鍵標準(例如用于汽車功能安全的ISO 26262和用于機載系統的DO-178B/C)都需要MC/DC。
這是一個簡單的代碼示例,假設x,y和z為布爾值:
If ( (x||y) && z) { doSomethingGood(); } else {doSomethingElse();}
在這種情況下,無論我的值是多少,該行都被“覆蓋”了。誠然,這是一種將所有內容都放在一行上的草率方法,但是您看到了問題。人們實際上以這種方式編寫代碼。但是,讓我們整理一下。
If ( (x||y) && z) { doSomethingGood(); } else { doSomethingElse(); /* because code should never doSomethingBad() */
一目了然,我可能會得出這樣的結論:我只需要兩個測試——一個將整個表達式評估為TRUE并執行doSomethingGood() (x=true, y=true, z=true),而另一個則評估為FALSE并執行doSomethingElse() (x=false, y=false, z=false)。行覆蓋率說我們很高興,“一切都經過測試。”
但是請稍等,可以通過多種方式測試主表達式:
這是一個簡單的示例,但它說明了這一點。我這里需要進行4個測試才能真正正確地覆蓋代碼,至少在我關心MC/DC覆蓋率的情況下。當我完成一半時,行覆蓋率會說100%。我將再一次不再詳細說明MC/DC的價值。這里的重點是,無論您使用哪種方法衡量覆蓋率,通過斷言進行驗證的內容都有意義是很重要的。
許多人陷入的另一個陷阱是添加了一種不復雜的工具來自動生成單元測試。
簡單的測試生成工具可以創建無需任何聲明即可執行代碼的測試。這樣可以避免測試變得嘈雜,但實際上意味著您的應用程序不會崩潰。不幸的是,這并不能告訴您應用程序是否在執行應做的事情,這很重要。
下一代工具通過根據它們可以自動捕獲的任何特定值創建斷言來工作。但是,如果自動生成會產生大量斷言,則最終會產生大量麻煩。這里沒有中間立場。您要么擁有易于維護但毫無意義的東西,要么擁有值得懷疑的維護噩夢。
首先,許多自動生成單元測試的開源工具看起來很有價值,因為您的覆蓋率非常快。真正的問題在于維護。通常,在開發過程中,開發人員會付出額外的努力來微調自動生成的斷言,以創建他們認為干凈的測試套件。但是,斷言是脆弱的,不能隨著代碼的更改而適應。這意味著開發人員在下次發布時必須再次執行大部分“自動”生成。測試套件可以重用。如果您無法重復使用它們,則說明您做錯了什么。
這也不能掩蓋一個可怕的想法,即在第一次運行時,當您具有較高的覆蓋率時,測試中的斷言沒有應有的意義。僅僅因為可以斷言某些東西,并不意味著應該這樣做,或者甚至是正確的事情。
public class ListTest { private List<String> list = new ArrayList<>(); @Test public void testAdd() { list.add(“Foo”); assertNotNull(list); } }
理想情況下,斷言將檢查代碼是否正常運行,并且當代碼工作不正常時,斷言將失敗。有很多斷言都不是很容易的,我們將在下面進行探討。
如果您要以覆蓋率高、可靠、干凈的測試套件為代價來拍攝高覆蓋率的產品,那么您將失去價值。一套維護良好的測試套件使您對代碼充滿信心,甚至是快速安全重構的基礎。嘈雜和/或毫無意義的測試意味著您不能依賴測試套件,不能重構,甚至不能發布。
人們對代碼進行衡量(尤其是根據嚴格的標準)時,會發現他們發現自己的代碼比自己想要的要低。通常,這最終導致他們追逐承保率。讓我們開始報道吧!現在,您可能會因為不合理的信念而陷入危險的境地,即自動化JUnit測試已經創建了有意義的測試,或者通過手工創建了意義不大且維護成本很高的單元測試。
在現實世界中,維護測試套件的持續成本遠遠超過了創建單元測試的成本,因此從一開始就創建良好的干凈單元測試非常重要。您會知道這一點,因為您可以在持續集成(CI)流程中始終運行測試。如果您僅在發行時運行測試,則表明測試噪音大。具有諷刺意味的是,這使得測試變得更糟,因為它們沒有得到維護。
軟件測試自動化還不錯,實際上,這是必要的,因為它具有當今常見的復雜性和時間壓力。但是,自動生成價值通常比其價值更麻煩。與隨意創建斷言相比,基于擴展值,監視實際系統以及創建復雜的框架、模擬和存根的自動化提供了更多的價值。
測量
第一步是衡量并獲得有關您當前覆蓋率的報告,否則,您將不會知道自己的位置以及情況是否會好轉。進行此操作時,衡量所有測試活動(包括單元、功能、手冊等)并正確匯總覆蓋率非常重要。這樣,您將盡最大的努力去努力——在完全未經測試的代碼上,而不是端到端測試涵蓋但沒有碰巧的代碼上單元測試。Parasoft可以準確地匯總來自多個運行和多種類型測試的代碼覆蓋率,從而為您提供準確的位置信息。有關此方面的更多信息,請參見我們的白皮書:全面的代碼覆蓋率—測試實踐的合計覆蓋率。
構架
為您創建單元測試框架的工具是一個很好的入門方法。確保這些工具連接到Mockito和PowerMock等常見的模擬框架,因為實際代碼很復雜,并且需要存根和模擬。但這還不夠,您需要能夠:
您可以手動完成所有這些操作,但是這會花費大量時間和精力。這是利用自動化的絕佳場所——例如,Parasoft Jtest在IDE中實時提供自動建議,并與開源框架(JUnit,Mockito,PowerMock等)集成,以幫助用戶創建、擴展和維護他們的JUnit測試套件并提供更廣泛的覆蓋率。如果您對此技術感到好奇,則可以了解有關人們為什么討厭單元測試又如何重新喜愛上它的更多信息。
如果覆蓋率對于您的項目來說是一個問題,請確保您對其進行了正確的衡量,并從您運行的所有測試中對所有方面進行了衡量。隨著您開始使用單元測試擴展覆蓋率,您可以利用指導性的測試創建來快速創建和擴展測試,以獲取有意義的可維護代碼覆蓋率。Parasoft Jtest將創建隨著代碼的增長和更改而可維護的測試,因此您不必一遍又一遍地執行相同的工作。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn