Android單元測試

單元測試業界標準:
MVP + Junit4 + Mockito + Hamcrest + Espresso + Dragger2

一、爲何要做單元測試

  1. App持續集成的時候需要一個集成測試保障其正確性(正確性)
  2. 頁面較複雜的時候,我們是否可以先測試業務邏輯的正確性(邊開發邊測試)
  3. 項目較大,編譯緩慢,測試業務邏輯部分(測試速度大幅提高)
  4. 對代碼結構、代碼健壯性、代碼可維護度都有很大提高
  5. 不用太擔心修改代碼後,會導致其它bug,單元測試集成測試會告訴我們

    other:蘑菇街的哥們說過:慢慢的你會發現,其實不是這樣的,純java的代碼其實真不少,而且往往是核心的邏輯所在

二、測些什麼

代碼結構:

Android中的MVC分層不清晰,我們更傾向於MVP,這裏列舉一些比較好的文章。

測試框架:

Android單元測試分爲:

Local Unit Tests (直接在JVM上進行測試):
  1.Junit4
  2.Mockito (最常用的Mock之一)
  3.Hamcrest(增加JUnit的測試能力)
  4.Robolectric(第三方:JVM中模擬Android)
Instrumented Tests (需要藉助儀器、模擬器測試):
  1.AndroidJUnitRunner (官方:InstrumentTestRunner升級版,支持Junit4,下面的UI測試框架需要與之結合使用)
  2.Espresso (官方:測試單獨App)
  3.UI Automator (官方:跨進程測試(多App之間進行測試))
  4.Robotium(第三方:基於Android 原生的Instruments)
  5.Appium (第三方:支持Android IOS自動化測試)

  • OS: Apple’s UIAutomation
  • Android 4.2+: Google’s UiAutomator
  • Android 2.3+: Google’s Instrumentation. (Instrumentation support is provided by bundling a separate project, Selendroid)

測些什麼

  • Local Tests 測試業務邏輯層、部分Model層
  • Instrumented Tests 測試UI,測試用例
  • 測試方法的返回值
  • 測試操作流程中方法的調用情況(是否調用?調用幾次?被調用時傳入的參數值)

三、測試準備

1. Junit4

2. Mockito

Mock的概念(Mockito.mock):所謂的mock就是創建一個類的虛假的對象,在測試環境中,用來替換掉真實的對象,以達到兩大目的:
- 驗證這個對象的某些方法的調用情況,調用了多少次,參數是什麼等等
- 指定這個對象的某些方法的行爲,返回特定的值,或者是執行特定的動作
- 注意:需要將Mock對象注入到需要測試的類中

@RunWith(MockitoJUnitRunner.class)
@Mock > (Mock出一個對象,此對象的方法調用並不會真正調用)
@Spy > (Spy出的對象,調用其方法會真正執行)
@Captor > (用於抓取被調用方法的參數,進行驗證,也可以使用ArgumentCaptor new出來)
@InjectMocks > (只要在被測試類上標記@InjectMocks,Mockito就會自動將標記@Mock、@Spy等註解的屬性值注入到被測試類中。)

// 抓取mock對象方法的參數進行驗證:
// 驗證mTasksRepository對象調用了getTask,並且抓取此方法的第二個參數
verify(mTasksRepository).getTask(eq(testTask.getId()), mGetTaskCallbackCaptor.capture());

// 調用上一步抓取到的參數的onTaskLoaded方法
mGetTaskCallbackCaptor.getValue().onTaskLoaded(testTask);
// 預設mock對象某方法被調用時返回特定值:
Mockito.when(searchSchoolFragmentView.isActive()).thenReturn(true);
// 預設mock對象某方法被調用時執行doAnswer裏面自定義的邏輯:
// 也可以先
Mockito.doAnswer(new Answer() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        //這裏可以獲得傳給performLogin的參數
        Object[] arguments = invocation.getArguments();

        //callback是第三個參數
        NetworkCallback callback = (NetworkCallback) arguments[2];

        callback.onFailure(500, "Server error");
        return 500;
    }
}).when(mockUserManager).performLogin(anyString(), anyString(), any(NetworkCallback.class));

3. Hamcrest

Assert.assertThat(object,Matcher.xxxmethod(yy));
Matchers:匹配器 > Espresso也基於此
 

4. Espresso

組成部分:

  • ViewMachers:尋找用來測試的View
  • ViewAction:發送交互事件
  • ViewAssertions:檢測測試結果

View Machers: withId、withHint、allof(withId(),withHint())…
View Actions: click()、doubleClick()、pressBack()、openLick()…
View Assertions: matches、not、isDisplayed…

線程安全保障:

Espresso測試有個很強大的地方是它在多個測試操作中是線程安全的。

Espresso會等待當前進程的消息隊列中的UI事件,並且在任何一個測試操作中會等待其中的AsyncTask結束纔會執行下一個測試。這能夠解決程序中大部分的線程同步問題。

Espresso中有個API叫做registerIdlingResource,它可以讓你使用自定義的線程安全邏輯。(上面鏈接中有對registerIdlingResource詳細講解)

四、參考資料

蘑菇街小創
http://chriszou.com/

Android單元測試
http://www.chriszou.com/2016/04/13/android-unit-testing-start-from-what.html

解讀Android官方MVP項目單元測試
http://www.jianshu.com/p/cf446be43ae8

Android官網測試文檔
http://developer.android.com/intl/zh-tw/training/testing/start/index.html

dragger2:
(一)http://www.jianshu.com/p/cd2c1c9f68d4
(二)http://www.jianshu.com/p/1d42d2e6f4a5
(三)http://www.jianshu.com/p/65737ac39c44
dragger2:
http://www.cnblogs.com/tiantianbyconan/p/5092525.html

Android谷歌官方測試demo:
https://github.com/googlesamples/android-testing

Mockito講解
http://www.vogella.com/tutorials/Mockito/article.html
Mockito更詳細講解
http://hotdog.iteye.com/blog/search?query=Mockito

Espresso
http://blog.csdn.net/shandong_chu/article/details/47083753

Espresso IdlingResource
http://www.jianshu.com/p/95d075b90a2f

MVP快速開發框架Beam
https://github.com/Jude95/Beam

encleus簡化MVP
https://github.com/konmik/nucleus

五、下一篇文章以Android官方MVP架構示例項目解析談測試

Android官方MVP項目單元測試分析得很到位

發佈了39 篇原創文章 · 獲贊 9 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章