Android TDD 系列 — 12 UI 測試:使用Espresso
UI 測試在Android 的所有測試裡執行起來最花費時間的,成本最高。但當我們需要測試使用者如何使用App時,仍是有撰寫UI測試的必要。Espresso是一個讓你可以撰寫Android UI測試的框架。你可以用id或文字的方式來取得一個元件,模擬使用者點擊、輸入資料等使用者行為及驗證App上是否有出現預期的功能。
實體書,內容更豐富完整!
「Android TDD 測試驅動開發:從UnitTest、TDD到DevOps實踐」
在指定Id上的EditText上輸入文字
//在id為someId的元件上輸入Some Text
onView(withId(R.id.someId)).perform(typeText("Some Text"))
如果你無法用指定id的方式來取得元件,也可以用withText比對文字的方式來取得元件。
//取得是否有文字為Some text的元件存在
onView(withText("Some text")).check(matches(isDisplayed()))
點擊按鈕
//點擊Id為button的元件
onView(withId(R.id.button)).perform(click())
環境設定
在buide.gralde加上
dependencies {
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
範例
我們延續之前的範例:註冊功能,來做UI測試。
UI測試的程式跟Instrumented test 一樣都是放在androidTest裡
新增測試類別RegisterTest
。
在RegisterTest 上方加上@LargeTest
當你會用到網路存取資料、資料庫、多執行緒等等較花費時間,在你的測試類別上方加上@LargeTest
測試執行時間會超過1秒的,一般都會被歸為LargeTest。
@LargeTest
class RegisterTest {
}
開始測試
首先要開啟我們要測試的Activity。使用ActivityTestRule
來設定測試目標Activity, 可以讓你在開始測試之前,先開啟被測試的Activity。
class RegisterTest {
@Rule
@JvmField
var activityActivityTestRule = ActivityTestRule(MainActivity::class.java)
}
我們先為註冊成功撰寫一個UI測試,當輸入正確的帳號密碼時,會開啟至下一頁顯示註冊成功。
@Test
fun rightPassword_should_startActivity() { //輸入帳號
onView(withId(R.id.loginId)).perform(typeText("a123456789"), ViewActions.closeSoftKeyboard())
//輸入密碼
onView(withId(R.id.password)).perform(typeText("a111111111"), ViewActions.closeSoftKeyboard()) //點選註冊按鈕
onView(withId(R.id.send)).perform(click()) //註冊成功,導至成功頁。
onView(withText("註冊成功")).check(matches(isDisplayed()))
}
執行UI測試的方式一樣是按綠色的三角型,就可以看到模擬器被開起來自動測試。
註冊失敗也是需要測試的。註冊失敗需要驗證是否有Alert。
@Test
fun wrongPassword_should_alert() { //輸入帳號
onView(withId(R.id.loginId)).perform(typeText("a123456789"), ViewActions.closeSoftKeyboard())
//輸入密碼
onView(withId(R.id.password)).perform(typeText("1234"), ViewActions.closeSoftKeyboard()) //點選註冊按鈕
onView(withId(R.id.send)).perform(click()) //註冊失敗,Alert
onView(withText("錯誤"))
.inRoot(isDialog())
.check(matches(isDisplayed()))
}
一樣執行測試,就可以看到測試通過的綠燈了。
這裡我們重構一下測試程式碼,下面這段是在輸入正確帳密的程式。
@Test
fun rightPassword_should_startActivity() { //輸入帳號
onView(withId(R.id.loginId)).perform(typeText("a123456789"), ViewActions.closeSoftKeyboard())
//輸入密碼
onView(withId(R.id.password)).perform(typeText("a111111111"), ViewActions.closeSoftKeyboard()) ...
}
把輸入帳號及密碼擷取方法,這裡其實我們只要知道輸入的帳密是要可以通過檢查的,細節我們應該將其封裝起來。
@Test
fun rightPassword_should_startActivity() { //輸入正確的帳密
inputRightRegisterData() ...
}
同樣的,將註冊失敗的測試裡的輸入錯誤帳密的部分,重構為一個function。
@Test
fun wrongPassword_should_alert() { inputWrongRegisterData() ...
}
其他驗證的方式
- text is:檢查文字內容是否是該文字
- exists:檢查View元件是存在於於螢幕可見的View中。
- does not exist:檢查View元件是不存在於於螢幕可見的View中。
Record Espresso Test 錄測試
你還可以使用錄制的方式來產生測試程式碼。
Run > Record Espresso Test
選擇要測試的裝置,可以在模擬器或實體裝置。
在下圖右邊的模擬器直接操作App,左邊就會依照你在App做了哪些動作,錄制下結果。
接著要驗證是否有出現「註冊成功」的字,點擊Add Assertion
點選一下右邊的「註冊成功」,左下角就會出現建議的驗證方式。
點選OK,儲存測試類別。這樣就可以透過錄制的方式來產生測試程式碼
錄好測試程式,也請記得測試程式碼也是要重構的,把測試程式碼當為Production Code的一部分。
Espesso的錄制功能其實還是有些問題,像是錄制時模擬器及錄制都很慢,也會有些測試情境是無法用錄制的。大部分時候你直接寫測試程式還是比較快。建議可以把UI測試的錄制拿來當作在初學時如何取得畫面元件的方式來學習。
範例下載:
https://github.com/evanchen76/uitestsample
參考:
https://developer.android.com/training/testing/espresso
Android TDD 系列
下一篇:13 使用Robolectric 撰寫 Android test