我們常常聽到這樣的問題:“為什么軟件的開發者們不適合測試他們自己開發的軟件?”。事實上,要回答這個問題需要明白開發者去進行測試的目的。本篇文章不會深入到自動化測試的具體細節,是對如何減少重復測試進行簡單實踐,讓業務開發人員能夠簡單快速上手才是最終目的。
開發人員測試自己所開發軟件的行為就像學生在完成考試后對自己的成績進行評估,所以可能會出現下面的問題:
- 開發人員對其所寫代碼有主觀認同感
- 開發人員對軟件過于樂觀的心態
- 開發人員對需求易產生偏差與混淆
- 開發人員擅長修復但不擅長拆解
- 開發人員缺乏對軟件后續開發的展望
- 開發人員缺乏測試經驗和方法
開發者測試的目的
就如前面所說,軟件開發者測試自己開發的程序好像并沒多大意義,測試工程師具有很多優勢條件,那作為開發者進行自動化測試的目的是什么?
其實從下面的圖就能解釋一切,程序員這個職業存在的意義不就是最大化利用機器,通過自動化來完成工作嗎?
作為軟件開發者需求很明顯,當需要對自己開發的功能進行驗證時,總是需要反復調試后才能提測。這不可避免的需要我們重復UI操作去覆蓋測試路徑,通過查看界面內容和日志輸出驗證問題。而UI自動化測試恰恰可以滿足這一點,減少我們重復操作ui驗證的步驟。
Android自動化測試介紹
關于Android自動化測試,可以去官網看一下介紹Getting Started with Testing。
本篇文章不會對深入到自動化測試的細節進行描述,只是作為開發人員對如何減少重復工作量進行簡單的實踐,所以這里直接推薦騰訊U測社區的一篇文章:5個最佳的Android測試框架,有興趣的童鞋可以了解一下目前主流的自動化測試框架。
解放你的雙手
作為一個業務開發人員,解放雙手進行功能驗證性測試才是最根本的需求,所以下面介紹一下使用Espresso進行UI自動化測試的流程。
為什么選擇Espresso測試框架?
很簡單,Espresso是Google針對Android平臺開源的一款最新的Android自動化測試框架。不用考慮跨平臺、兼容性等各種問題,最貼合需求才是最好的。
UI自動化測試依據
UI自動化測試的基本思路:把自己當成用戶,只關注我能看到的東西。
我們把自己作為使用程序的最終用戶,要讓機器模擬我的測試過程,那么就需要針對那些我能看到的東西,也就是UI組件進行驗證。
比如說,作為用戶并不關心某個網絡請求返回值的具體數據是否正確,我關心的是能在UI上看到希望看到的結果。
基于此,做各個測試用例的一個通用的思路就是:找到某個元素,做一些操作,檢查結果。這里包含了三個流程:
- 找元素:找到UI上測試所針對的元素;
- 做操作:給這個元素做一些操作;
- 檢查結果:這個元素做出了我期望的行為。
再直觀一點,我們測試向一個EditText輸入一段文字,那么整個過程就可以描述為:
- 找元素:找到EditText組件;
- 做操作:向EditText輸入字符串;
- 檢查結果:EditText顯示了我輸入的字符串,驗證內容是否符合。
以上三個小步驟實際上也是我們作為用戶在使用一個APP的時候所遵循的流程。而我們的測試也是基本遵循這樣一個流程的。下面是官方文檔中給出的一個簡單測試用例的代碼:
@Test
public void greeterSaysHello() {
onView(withId(R.id.name_field))
.perform(typeText("Steve"));
onView(withId(R.id.greet_button))
.perform(click());
onView(withText("Hello Steve!"))
.check(matches(isDisplayed()));
}
代碼邏輯也是典型的三步:
首先通過withId方法找到了id為name_field的EditText組件,并且調用typeText方法對其進行設置text內容為"Steve";
再通過withId方法找到id為greet_button的Button組件,掉頭click方法模擬點擊該按鈕;
最后通過withText方法查找text內容等于"Hello Steve!"的TextView組件,調用check方法判斷該組件是否匹配(matches方法)是否可見狀態(isDisplayed)。
UI自動化具體實例
這里建議參照官方文檔給出的步驟進行實踐,示例給出自己在實踐demo中配置自動化測試的基本步驟。Espresso setup instructions
1. 在gradle添加支持
在app目錄下build.gradle中dependencies設置對Espresso庫的編譯依賴,在android.defaultConfig設置InstrumentationRunner。
// 在app目錄下的build.gradle添加對Espresso的依賴
dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestCompile 'com.android.support.test.espresso:espresso-idling-resource:2.2.2'
...
}
// 在app目錄下的build.gradle中設置instrumentation runner
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
2. 創建Test Case文件
在Android Studio執行測試的代碼類文件需要在app模塊的androidTest文件夾下創建。如下圖所示:
3. 編寫測試用例代碼
比如當我們為TestActivity創建TestActivityTest測試用例類文件成功以后:
- 首先需要在測試用例類的類體前添加@RunWith的注解,并設置測試運行平臺為AndroidJUnit4
- 如果允許測試需要較大消耗,可以使用@LargeTest注解
- 設置ActivityTestRule用來指明被測試的Activity,使用@Rule注解。
運行測試時用例時會自動啟動到對應的Activity,并且通過ActivityTestRule的示例獲取到被測試Activity的context。
- 編寫測試方法,按照前面說的“找元素,做操作, 驗證結果”三個步驟編 寫測試方法,使用@Test注解。
建議使用test作為方法名的開頭,這樣可以更好區分普通方法和測試方法
如上圖所示,代碼為TestActivity創建了測試用例類TestActivityTest,其中testDeciceName為其中一個測試用例方法。該方法主要是通過id查找到EditText,自動輸入內容后模擬點擊id為bt_get_string的button,最后驗證textview顯示內容是否符合。
4. 運行Test Case
在Android Studio的終端中輸入gradlew connectedAndroidTest 或 gradlew cAT
執行測試用例。
整體運行效果如下:
5. 異步和延遲
有時點擊一個按鈕,ui操作后需要執行一個較為耗時的事情時通常會采用異步回調的方式通知顯示結果,這時進行UI自動化測試的第三步驗證結果的時機就不能才能同步的方式去執行,而是需要做異步回調通知執行或延遲執行。
Espresso提供了原生的異步測試支持,通過實現IdlingResource接口,復寫getName()、isIdleNow()、registerIdleTranstionCallback()方法。
如圖所示FuncExecuteIdlingResource:
然后在測試用例的類中注冊和反注冊接口:
Espresso.registerIdlingResources(idlingResource);
當方法執行完成,調用ResourceCallback.onTransitionToIdle();則會進行回調通知測試線程繼續執行驗證代碼。
總結
一切能自動化完成的測試操作就不要浪費時間用手動完成。后續將會對單元測試進行說明,共同學習,相互提升。