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