iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
2
Mobile Development

Android TDD 測試驅動開發系列 第 16

Day16 - Android 測試小結

  • 分享至 

  • xImage
  •  

我們來為第二單元「在Android 的測試」小結一下,在這個單元我們介紹了Android的各種測試:

  • local Unit Test
  • Local Unit Test 使用 Robolectric
  • Instrumented Test
  • UI Test

Local Test
Local Test的執行速度最快,我們應該讓App的測試儘可能都是Local Test。儘可能讓你的商業邏輯與View所負責的部分拆開,你就可以有更多的Local Test。

Instrumented Test
Instrumented tests ,當被測試的物件與Android framework有關連時,就需要使用Instrumented tests。這個測試需要在模擬器或實體機器執行,執行的速度較慢。

UI Test
UI測試主要用來測試使用者與App的互動,當然也是需要在模擬器或實體機器上執行。

Local Unit Test 使用 Robolectric
Robolectric讓你可以用單元測試的方式來測試與Instrumented tests。

Instrumented tests 與 UI Test 的比較

這兩種測試都是寫在androidTest的目錄下,因為都是需要模擬器或實機。Instrumented 的中文的意思是「設備、儀器」指的就是在機器上的測試,跟UI Test的差異在於UI Test特別強制使用者的互動。例如你要測試儲存資料SharedPreferened就是Instrumented test。或是要測試Service的話,也是Instrumented test。

UI Test 與 Robolectric 的比較

我們在這個單元分別使用了UI測試:Espresso與Robolectric來測試View的行為,而這兩種有什麼差異呢?

UI測試的測試目錄在androidTest。
Robolectric的測試目錄在test。

UI測試在模擬器或實機測試。
Robolectric的測試在JVM測試。

UI測試失敗時,較慢找到失敗的原因。
Robolectric屬於單元測試,較快找到失敗的原因。

除了這兩個差異,更重要的是測試的行為是不一樣的。

在UI測試Espresso的測試註冊用驗證是否有「註冊成功」的字來確認。

@Test
fun rightPassword_should_startActivity() {

    //輸入正確的帳密
    inputRightRegisterData()

    //點選註冊按鈕
    onView(withId(R.id.send)).perform(click())

    //註冊成功,導至成功頁。
    onView(withText("註冊成功")).check(matches(isDisplayed()))
}

而在Robolectric的測試註冊成功則是驗證Intent。

@Test
fun registerSuccessShouldDirectToResult() {
    //arrange
    val shadowActivity = Shadows.shadowOf(activity)

    val userId = "A123456789"
    val userPassword = "a123456789"

    activity.loginId.setText(userId)
    activity.password.setText(userPassword)

    //點下註冊按鈕
    activity.send.performClick()

    //驗證註冊成功時,是否有開啟ResultActivity
    val nextIntent = shadowActivity.nextStartedActivity
    assertEquals(nextIntent.component!!.className, ResultActivity::class.java.name)
    assertEquals(1, nextIntent.extras!!.size())
    assertEquals(userId, nextIntent.extras!!.getString("ID"))
}

Robolectric 的重點在於,當帳號、密碼欄位設定為錯誤的帳密時,傳給Intent的值是否正確。UI測試的重點在於,當帳號、密碼欄位輸入錯誤的帳密時,是否有在畫面上看到註冊成功的字。UI測試是有「輸入文字」的行為。在Robolectric,我們是直接讓EditText的Text給值,跟UI測試的開啟鍵盤輸入文字是不一樣的。所以UI測試較能測試到使用者真實的互動。在選擇用哪一種測試時,你需要同時考慮的是測試的效率與使用者的互動。

從測試金字塔再來回顧一下。
https://ithelp.ithome.com.tw/upload/images/20190930/20111896srXNT4ZYFY.png

圖片來源 Google IO 2017

如果以測試金字塔來說,UI測試就會算是第二層的Integration test,而Robolectric則會是第一層的單元測試。
這裡有一個我們沒有提到太多的E2E測試,端點對端點的測試。當App會連接WebAPI時,這時App與WebAPI就是兩個不同的端點。以註冊帳號為範例,這樣的測試就必須同時驗證註冊後是否真的有資料進到資料庫。這樣的測試是最耗時的,也是最容易失敗的,如果當下的網路異常,或資料庫裡已有一筆相同被註冊過的帳號,皆會導至註冊失敗。在下個單元介紹WebAPI時,將再介紹在有呼叫WebAPI功能的App做測試。

Android 的每一種測試是對映到測試金字塔的哪一層其實並不是很重要,測試金字塔要傳達的概念只是測試應有不同的層度:
1.越上層成本越高,測試越慢。
2.越上層的測試應越少。

如果反過來的話,則會是像下圖的這個「測試冰淇淋」,最上層的手動測試最多,最下層的單元測試最少。可以想像這樣的測試方式有多耗時。
https://ithelp.ithome.com.tw/upload/images/20190930/2011189605SEqfec4S.png

第二單元「在Android的測試」就到這告一個段落,下個單元我們將開始進入到Android測試的架構篇,介紹MVP及MVVM的架構,並為範例加入串接WebAPI,同時開始處理非同步的議題。

出版書:
Android TDD 測試驅動開發:從 UnitTest、TDD 到 DevOps 實踐


上一篇
Day15 - Gradle 測試環境設定
下一篇
Day17 - Android MVP 架構
系列文
Android TDD 測試驅動開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言