Android 單元測試
保證最小的獨立單元(函數)的代碼是否正確。
詳細介紹:
https://github.com/leeowenowen/AndroidUnitTest
推薦文章:
http://chriszou.com/2016/06/07/android-unit-testing-everything-you-need-to-know.html
為什么做單元測試
- 方便重構,修改代碼:改前跑一遍,改后跑一遍
- 更快的反饋:每開發完一個獨立模塊后就可以測試
- 節約時間:30%編碼,70%測試。改一次,編譯一次。
- 提升代碼設計:TDD,每個類更小,職責更明確,功能單一。從維護者的角度去編寫代碼。
- 對軟件質量的提升:從代碼層面發現bug
測什么
單元測試,是為了測試某一個類的某一個方法能否正常工作,而寫的測試代碼。它不是測試一整個流程。而非public方法是這個類的實現細節,我們并不關心,我們只關心某一個public方法的輸入、輸出。
- 有返回值:輸入響應參數,查看返回值
- 沒返回值:驗證方法被調用
問題
- 一般來說,單元測試不會接觸到數據庫,不會接觸到網絡,不會接觸到一些復雜的外部環境,如果有的話,那可能是你測試的方式有誤,測試的粒度不夠“單元”。
- public,private方法不夠科學
- 需要增加與業務無關的代碼去測試代碼
- 需要模擬Android的類,生命周期以及運行環境
- MVP,MVVM, DI將業務層完全剝離出來,變成純java方便測試
- TDD
如何測試
Mock
所謂的mock就是創建一個類的虛假的對象,在測試環境中,用來替換掉真實的對象,以達到兩大目的:
- 驗證這個對象的某些方法的調用情況,調用了多少次,參數是什么等等
- 指定這個對象的某些方法的行為,返回特定的值,或者是執行特定的動作
Mockito
中文文檔:https://github.com/hehonghui/mockito-doc-zh
PowerMock
PowerMock支持靜態,final以及私有方法的mock
官網:https://github.com/powermock/powermock
推薦文章:https://my.oschina.net/jackieyeah/blog/157076
測試框架
JUnit
單元測試的本質依舊是驗證函數的功能,測試框架也是JUnit
setup(@Before)
執行操作(@Test,@After)
-
驗證結果(@Assert):
- assertEquals(expected, actual)
- assertTrue/False(boolean condition)
- assertNull/NotNull(Object obj)
如果有異常:
@Test(expected = Exception.class)
沒拋出,測試失敗
Robolectric(推薦)
JVM上無法調用安卓相關的類,所以需要使用Robolectric來模擬android的運行環境。
使用Robolectric后也可以測試android中的視圖屬性,點擊事件,跳轉等。
Android Testing Support Library
谷歌官方提供的測試工具
https://google.github.io/android-testing-support-library/
- Espresso(UI自動化測試)
- AndroidJUnitRunner(單元測試)
- Instrumentation(可模擬Android環境,類似Robolectric)
- Unit4 Rules
- UiAutomator
經驗
test和androidTest
構建項目時會自動創建兩個測試的package:androidTest和test,沒有也可以自己創建,我個人簡單的理解為:
- test:不需要依賴運行環境的JUnit單元測試代碼放這里
- androidTest: 需要依賴運行環境(模擬器或真機)的集成測試,UI測試代碼放這里
創建測試類
- 打開要測試的類
- 點擊Android Studio菜單欄 -> Navigate -> Test -> Crate test case...
- 選擇需要測試的函數,以及測試框架等等
測試Realm
https://github.com/realm/realm-java/tree/master/examples/unitTestExample
測試Rxjava
http://www.programcreek.com/java-api-examples/index.php?api=rx.observers.TestSubscriber
gradle執行UnitTest
-
./gradlew test
運行所有Module下的測試 - test 命令實際包含了testDebug和testRelease以及其他渠道包(如果有的話,如:testAmazonDebug,testAmazonRelease)
- 在
{@projectName}/{@moduleName}/build/reports/tests
下會生成測試結果的報告 - 如果運行時出現錯誤會中斷,可以使用
./gradlew test --continue
來不中斷執行 - 如果想單獨測試某個模塊也可以使用
./gradlew {@moduleName}:test
比如./gradlew lib_dao:testReleaseUnitTest
Jenkins CI
如果想在build結束后生產Unit Test的報表:
- 確定在構建時執行了gradle test相關的task
- 在最后一步添加一個build step,叫做
Publish Junit test result report
,將生成的所有測試結果文件(xml)的路徑添加到Test report XMLs
參數中,例如lib_dao/build/test-results/release/*.xml