我們常常聽到這樣的問題:“為什么軟件的開發(fā)者們不適合測試他們自己開發(fā)的軟件?”。事實(shí)上,要回答這個問題需要明白開發(fā)者去進(jìn)行測試的目的蜜自。本篇文章不會深入到自動化測試的具體細(xì)節(jié),是對如何減少重復(fù)測試進(jìn)行簡單實(shí)踐卢佣,讓業(yè)務(wù)開發(fā)人員能夠簡單快速上手才是最終目的重荠。
開發(fā)人員測試自己所開發(fā)軟件的行為就像學(xué)生在完成考試后對自己的成績進(jìn)行評估,所以可能會出現(xiàn)下面的問題:
- 開發(fā)人員對其所寫代碼有主觀認(rèn)同感
- 開發(fā)人員對軟件過于樂觀的心態(tài)
- 開發(fā)人員對需求易產(chǎn)生偏差與混淆
- 開發(fā)人員擅長修復(fù)但不擅長拆解
- 開發(fā)人員缺乏對軟件后續(xù)開發(fā)的展望
- 開發(fā)人員缺乏測試經(jīng)驗(yàn)和方法
開發(fā)者測試的目的
就如前面所說虚茶,軟件開發(fā)者測試自己開發(fā)的程序好像并沒多大意義戈鲁,測試工程師具有很多優(yōu)勢條件,那作為開發(fā)者進(jìn)行自動化測試的目的是什么嘹叫?
其實(shí)從下面的圖就能解釋一切婆殿,程序員這個職業(yè)存在的意義不就是最大化利用機(jī)器,通過自動化來完成工作嗎待笑?
作為軟件開發(fā)者需求很明顯鸣皂,當(dāng)需要對自己開發(fā)的功能進(jìn)行驗(yàn)證時,總是需要反復(fù)調(diào)試后才能提測暮蹂。這不可避免的需要我們重復(fù)UI操作去覆蓋測試路徑,通過查看界面內(nèi)容和日志輸出驗(yàn)證問題癌压。而UI自動化測試恰恰可以滿足這一點(diǎn)仰泻,減少我們重復(fù)操作ui驗(yàn)證的步驟。
Android自動化測試介紹
關(guān)于Android自動化測試滩届,可以去官網(wǎng)看一下介紹Getting Started with Testing集侯。
本篇文章不會對深入到自動化測試的細(xì)節(jié)進(jìn)行描述,只是作為開發(fā)人員對如何減少重復(fù)工作量進(jìn)行簡單的實(shí)踐帜消,所以這里直接推薦騰訊U測社區(qū)的一篇文章:5個最佳的Android測試框架棠枉,有興趣的童鞋可以了解一下目前主流的自動化測試框架。
解放你的雙手
作為一個業(yè)務(wù)開發(fā)人員泡挺,解放雙手進(jìn)行功能驗(yàn)證性測試才是最根本的需求辈讶,所以下面介紹一下使用Espresso進(jìn)行UI自動化測試的流程。
為什么選擇Espresso測試框架娄猫?
很簡單贱除,Espresso是Google針對Android平臺開源的一款最新的Android自動化測試框架。不用考慮跨平臺媳溺、兼容性等各種問題月幌,最貼合需求才是最好的。
UI自動化測試依據(jù)
UI自動化測試的基本思路:把自己當(dāng)成用戶悬蔽,只關(guān)注我能看到的東西扯躺。
我們把自己作為使用程序的最終用戶,要讓機(jī)器模擬我的測試過程,那么就需要針對那些我能看到的東西录语,也就是UI組件進(jìn)行驗(yàn)證倍啥。
比如說,作為用戶并不關(guān)心某個網(wǎng)絡(luò)請求返回值的具體數(shù)據(jù)是否正確钦无,我關(guān)心的是能在UI上看到希望看到的結(jié)果逗栽。
基于此,做各個測試用例的一個通用的思路就是:找到某個元素失暂,做一些操作彼宠,檢查結(jié)果。這里包含了三個流程:
- 找元素:找到UI上測試所針對的元素弟塞;
- 做操作:給這個元素做一些操作凭峡;
- 檢查結(jié)果:這個元素做出了我期望的行為。
再直觀一點(diǎn)决记,我們測試向一個EditText輸入一段文字摧冀,那么整個過程就可以描述為:
- 找元素:找到EditText組件;
- 做操作:向EditText輸入字符串系宫;
- 檢查結(jié)果:EditText顯示了我輸入的字符串索昂,驗(yàn)證內(nèi)容是否符合。
以上三個小步驟實(shí)際上也是我們作為用戶在使用一個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組件,并且調(diào)用typeText方法對其進(jìn)行設(shè)置text內(nèi)容為"Steve"潮罪;
再通過withId方法找到id為greet_button的Button組件康谆,掉頭click方法模擬點(diǎn)擊該按鈕;
最后通過withText方法查找text內(nèi)容等于"Hello Steve!"的TextView組件嫉到,調(diào)用check方法判斷該組件是否匹配(matches方法)是否可見狀態(tài)(isDisplayed)沃暗。
UI自動化具體實(shí)例
這里建議參照官方文檔給出的步驟進(jìn)行實(shí)踐,示例給出自己在實(shí)踐demo中配置自動化測試的基本步驟何恶。Espresso setup instructions
1. 在gradle添加支持
在app目錄下build.gradle中dependencies設(shè)置對Espresso庫的編譯依賴孽锥,在android.defaultConfig設(shè)置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中設(shè)置instrumentation runner
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
2. 創(chuàng)建Test Case文件
在Android Studio執(zhí)行測試的代碼類文件需要在app模塊的androidTest文件夾下創(chuàng)建导而。如下圖所示:
3. 編寫測試用例代碼
比如當(dāng)我們?yōu)門estActivity創(chuàng)建TestActivityTest測試用例類文件成功以后:
- 首先需要在測試用例類的類體前添加@RunWith的注解忱叭,并設(shè)置測試運(yùn)行平臺為AndroidJUnit4
- 如果允許測試需要較大消耗,可以使用@LargeTest注解
- 設(shè)置ActivityTestRule用來指明被測試的Activity今艺,使用@Rule注解韵丑。
運(yùn)行測試時用例時會自動啟動到對應(yīng)的Activity,并且通過ActivityTestRule的示例獲取到被測試Activity的context虚缎。
- 編寫測試方法撵彻,按照前面說的“找元素钓株,做操作, 驗(yàn)證結(jié)果”三個步驟編 寫測試方法陌僵,使用@Test注解轴合。
建議使用test作為方法名的開頭,這樣可以更好區(qū)分普通方法和測試方法
如上圖所示碗短,代碼為TestActivity創(chuàng)建了測試用例類TestActivityTest受葛,其中testDeciceName為其中一個測試用例方法。該方法主要是通過id查找到EditText偎谁,自動輸入內(nèi)容后模擬點(diǎn)擊id為bt_get_string的button总滩,最后驗(yàn)證textview顯示內(nèi)容是否符合。
4. 運(yùn)行Test Case
在Android Studio的終端中輸入gradlew connectedAndroidTest 或 gradlew cAT
執(zhí)行測試用例巡雨。
整體運(yùn)行效果如下:
5. 異步和延遲
有時點(diǎn)擊一個按鈕闰渔,ui操作后需要執(zhí)行一個較為耗時的事情時通常會采用異步回調(diào)的方式通知顯示結(jié)果,這時進(jìn)行UI自動化測試的第三步驗(yàn)證結(jié)果的時機(jī)就不能才能同步的方式去執(zhí)行铐望,而是需要做異步回調(diào)通知執(zhí)行或延遲執(zhí)行冈涧。
Espresso提供了原生的異步測試支持,通過實(shí)現(xiàn)IdlingResource接口正蛙,復(fù)寫getName()督弓、isIdleNow()、registerIdleTranstionCallback()方法乒验。
如圖所示FuncExecuteIdlingResource:
然后在測試用例的類中注冊和反注冊接口:
Espresso.registerIdlingResources(idlingResource);
當(dāng)方法執(zhí)行完成咽筋,調(diào)用ResourceCallback.onTransitionToIdle();則會進(jìn)行回調(diào)通知測試線程繼續(xù)執(zhí)行驗(yàn)證代碼。
總結(jié)
一切能自動化完成的測試操作就不要浪費(fèi)時間用手動完成徊件。后續(xù)將會對單元測試進(jìn)行說明,共同學(xué)習(xí)蒜危,相互提升虱痕。