編寫移動應用程序很難,編寫好的和可維護的應用程序就更加困難了。在開發過程中,我們需要保證對代碼庫的每次修改不會降低代碼質量和功能的可用性。
在現代的移動應用開發中,很難想象在沒有編寫測試特別是單元測試的情況下,你可以做出一個可靠的和可維護的應用。但我們經常遇到一個問題:要編寫多少的測試用例才能足夠保證這段代碼能夠被測試正確的覆蓋。嗯,這沒有明確的答案,但今天我想介紹一個名為 JaCoCo 這款很棒的工具,它有助于保證有價值的代碼被單元測試覆蓋到。
JaCoCo 全稱是 Java Code Coverage tool,它已經在 Java 開發者中使用數十年了,但如果配置得當的話, Android 開發者也可以利用它獲得益處。社區已經有很多文章介紹 Android 工程中如何配置 JaCoCo 從而生成測試覆蓋報告,因此我就不再深入介紹這個主題。相反我將展示如何為 JaCoCo 測試覆蓋配置自動校驗功能,從而方便將其引入你的構建或者 CI 管道(pipeline)中。
首先讓我們看一個很簡單的 App,它包含兩個頁面:登錄頁面和主頁面。
請注意,這個示例工程只作演示用途,并不具備作為生產版本發布和使用的能力。
你可以在 Github:https://github.com/sgrekov/AndroidJacocoSample 上找到這個工程的完整代碼。
在這個示例工程中我實現了一個很基礎的 MVP 模式。這意味著我們將 Activities 視為被動的 View,所有有用的 UI 邏輯放在 Presenters 中。讓我們仔細看下 LoginPresenter,它有一個鍵盤輸入處理,登錄和密碼的校驗,以及授權邏輯本身。如果一切校驗沒有問題的話,那么登錄成功后我們就進入 MainActivity。在 LoginPresenterTest 中有一些單元測試。MVP 模式的規則是保持 View 層擁有盡可能少的代碼,同時,將業務邏輯保留在 Presenters 中,從而使得這部分邏輯代碼能夠很容易被單元測試覆蓋到。我們將按這種方式來配置 JaCoCo。我們將忽略 View 層和一些 Android 相關的類,為除此以外其他的類的代碼生成測試覆蓋報告。
如果我們的工程結構是按照特性來組織的,那么通過配置 'com/androidjacoco/sample/**/view/**.*' 這個過濾器規則就可以忽略現在以及將來可能增加的所有的 View 類。
現在,如果我們在命令行中執行:
我們將得到類似下面這樣一份報告:
這里我們可以看到報告中展示了一些數據類和 Presenters 的覆蓋率。
我們對下面三列感興趣:
Missed Instructions:提供關于被執行(譯者注:指被單元測試覆蓋到)或者沒有被執行的代碼量信息,單位是一條 Java 字節碼指令。
Missed Branches:用于計算一個方法中此類分支的總個數,并確定被執行或者沒有被執行的分支數量。
Classes:一個類只有當其中至少一個方法被執行過,才認為這個類是已執行的。
關于報告的更詳細信息可以參見:http://www.jacoco.org/jacoco/trunk/doc/counters.html。
讓我們看一下 LoginPresenter 類,并確保其中確實有很多沒有被執行到的指令和分支。
這里也要注意一下,匿名類,例如上面代碼中的 SingleObserver 或者 Consumer 類,在報告中會當作獨立的類來計算,正如我們在上面報告的 com.androidjacoco.sample.login.presenter 這個包所對應的 classes 列的值可以看到的。
現在如果我們不想讓測試覆蓋率如此低的代碼進入到生產環境中,我們能做些什么呢?JacocoCoverageVerification 這個 task 能夠幫我們解決這個問題!
這個 task 依賴于前面的 customJacocoTestReport task,如果執行它,將會首先生成測試覆蓋報告然后接著對其進行分析。這個 task 的配置中包含如何找到源代碼類所在的路徑,以及 violationRules 配置塊。violationRules 配置塊本身又包含了一些規則塊,只要你愿意,你可以添加盡可能多的這種規則塊。在這個例子中,我配置了三個規則塊:
規則一
如果沒有被單元測試覆蓋到的指令比率高于 60%,那么構建將會失敗:
規則二
如果代碼分支(if,switches 等)有多達 80% 以上沒有被單元測試覆蓋到,那么構建將會失敗:
規則三
在這個規則中我聲明了在 presenter 包中的每個類都必須至少有一個單元測試。請注意所有匿名類都會被當作一個個獨立的類來對待。
想要了解更多關于規則的語法,可查看:http://www.jacoco.org/jacoco/trunk/doc/ant.html。(譯者注:關于在 gradle 中配置 JaCoCo,可以參見:https://docs.gradle.org/current/userguide/jacoco_plugin.html)
此時我們執行命令:
將會得到如下所示的由于違反規則所導致的錯誤:
從上面可以看到,示例工程的覆蓋率不符合我們規則,因此需要編寫更多的單元測試!
在這個示例工程倉庫的 VerificationPassed 分支,你可以看到覆蓋率滿足規則的代碼。通過這種方式,你可以配置構建腳本,并將測試覆蓋率驗證添加到構建過程中。
JaCoCo 是一個功能強大的工具,可以幫助你增加代碼倉庫的測試覆蓋率。當然,如何定義規則和代碼覆蓋率取決于你的和具體項目的需求,但這是一個很好的代碼倉庫的健康指標,值得嘗試將其引入你的構建管道中。在我們的項目中,測試覆蓋率從開始的 0.4 慢慢增加到 0.6,并且還在繼續增長。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。