Android自動化測試工具 UiAutomator使用詳解
1.介紹
Android團隊在4.1版本(API 16)中推出了一款全新的UI自動化測試工具UiAutomator,用來幫助開發人員更有效率的完成App的Debug工作,同時對於測試人員也是一大福音,為什麼這麼說呢?
測試:“我發現了一個bug,你寫的App開啟A頁面,再開啟B頁面有時會出現閃屏問題。”
開發:“嗯?還有這樣的問題,復現給我看看。(內心獨白:我寫的App怎麼會有bug,一定是你用的姿勢不對)”
測試:一段忙碌的操作之後…“咦,怎麼不出現了?”
開發:“那你先回去吧,復現再告訴我。”
幾天過去了…
測試:滿心歡喜狀,“上次那個問題我復現了,操作給你看….我去,怎麼又不出現了!”
開發:“是不是裝置有問題,你換個裝置再試試呢?”
測試:“寶寶心裡苦,但是寶寶不說!”
有了UiAutomator之後:
測試:“我發現了一個bug,你寫的App開啟A頁面,再開啟B頁面有時會出現閃屏問題。”
開發:“這個簡單,我用UiAutomator寫個測試用例,分分鐘解決。”
測試:“厲害了Word哥!”
全劇終!
UiAutomator提供了以下兩種工具來支援UI自動化測試:
uiautomatorviewer:用來分析UI控制元件的圖形介面工具,位於SDK目錄下的tools資料夾中。
uiautomator:一個java庫,提供執行自動化測試的各種API。
2.環境搭建
本文使用了Android Studio作為IDE,Eclipse,Please go home!
首先在app根目錄的build.gradle檔案中加入依賴:
// AS預設配置,如果如果沒有記得加上
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
注意:uiautomator庫支援的最低版本為API 18,所以本篇文章開發環境的minSdkVersion為18。
配置testInstrumentationRunner為AndroidJunitRunner:
defaultConfig {
...
// 這個AS會為我們預設配置,如果沒有記得加上
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
看下完整的build.gradle檔案:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "com.yl.uiautomatordemo"
minSdkVersion 18
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
}
在dependencies中用到了compile、testCompile、androidTestCompile三種依賴方式,讓我們來看看他們有什麼區別:
compile:參與編譯,並且會打包到debug/release apk中。
testCompile:只參與單元測試編譯,不會打包到debug/release apk包中,不需要裝置支援。
androidTestCompile:只參與UI測試編譯,不會打包到debug/release apk包中,需要裝置支援。
除此之外還有Provided、APK、Debug compile和Release compile:
Provided:只參與編譯,不會打包到debug/release apk中。
APK:不參與編譯,只會打包到debug/release apk中。
Debug compile:只參與debug編譯,只會打包到debug apk中。
Release compile:只參與release編譯,只會打包到release apk中。
3.測試流程
1.安裝被測試App到手機中。
2.開啟UI分析工具uiautomatorviewer.bat,分析當前UI的介面元素,確保App的各個控制元件可以被測試工具獲取到。
3.根據App使用流程編寫測試用例。
4.執行測試用例進行測試,定位bug,解決bug。
4.實踐
分析UI的介面元素
啟動被測試App,開啟uiautomatorviewer.bat工具,點選左上角的Device Screenshot按鈕捕獲螢幕快照,如下圖所示,左側顯示螢幕快照,右側顯示佈局結構與控制元件屬性,控制元件屬性在編寫測試用例時會用到。
編寫測試用例
選擇File—New—New Project新建專案,和建立普通專案的流程相同,只不過不需要建立Activity,建立完成後,專案結構如下圖所示:
可以看到,在app—src目錄下,AS為我們自動建立了一個androidTest資料夾,用來編寫UI測試用例,同級還有一個test資料夾,用來編寫單元測試用例。
專案建立成功後,參考上文引入依賴,構建完成後,開始寫測試用例吧!等等,先別急,在此之前先普及一下uiautomator的常用API:
UiDevice:
裝置物件,通過UiDevice的getInstance(instrumentation)方法獲取,可以通過UiDevice例項來檢測裝置的各種屬性,比如獲取螢幕的方向、尺寸等,還可以通過UiDevice例項來執行裝置級別的操作,比如點選Home鍵、返回鍵等:
// 點選Home鍵 uiDevice.pressHome(); // 點選返回鍵 uiDevice.pressBack(); ...
UiSelector
用於獲取某些符合條件的UI控制元件物件,可以通過資源id、描述等熟悉獲取:
// 通過資源id獲取 new UiSelector().resourceId("com.yang.designsupportdemo:id/CollapsingToolbarLayout"); // 通過描述檔案獲取 new UiSelector().description("Navigate up") // 通過className獲取 new UiSelector().className("android.support.v7.widget.RecyclerView") ...
UiObject
代表一個UI控制元件,通過uiDevice的findObject(UiSelector)方法獲取,獲取到UiObject例項後,就可以對UI控制元件進行相關的操作,比如點選、長按等:
// 點選應用返回按鈕 UiObject back = uiDevice.findObject(new UiSelector().description("Navigate up")); back.click();
UiCollection
代表UI控制元件集合,相當於ViewGroup,比如介面中有多個CheckBox時,可以通過類名獲取到當前介面下的所有CheckBox,然後通過控制元件id獲取指定的CheckBox物件:
// 獲取指定的CheckBox物件 UiCollection uiCollection = new UiCollection(new UiSelector().className("類名")); UiObject checkBox = uiCollection.getChild(new UiSelector().resourceId(""));
UiScrollable
代表可滾動的控制元件,比如開啟設定的關於手機選項:
// 滑動列表到最後,點選About phone選項 UiScrollable settings = new UiScrollable(new UiSelector().className("android.support.v7.widget.RecyclerView")); UiObject about = settings.getChildByText(new UiSelector().className("android.widget.LinearLayout"), "About phone"); about.click();
看下滾動效果:
OK,常用API到這裡就說的差不多了,開始寫測試用例吧!
Talk is cheap, Show me the code.
public class UiTest extends TestCase {
public void testA() throws UiObjectNotFoundException {
// 獲取裝置物件
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
UiDevice uiDevice = UiDevice.getInstance(instrumentation);
// 獲取上下文
Context context = instrumentation.getContext();
// 啟動測試App
Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.yang.designsupportdemo");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
// 開啟CollapsingToolbarLayout
String resourceId = "com.yang.designsupportdemo:id/CollapsingToolbarLayout";
UiObject collapsingToolbarLayout = uiDevice.findObject(new UiSelector().resourceId(resourceId));
collapsingToolbarLayout.click();
for (int i = 0; i < 5; i++) {
// 向上移動
uiDevice.swipe(uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight(),
uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight() / 2, 10);
// 向下移動
uiDevice.swipe(uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight() / 2,
uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight(), 10);
}
// 點選應用返回按鈕
UiObject back = uiDevice.findObject(new UiSelector().description("Navigate up"));
back.click();
// 點選裝置返回按鈕
uiDevice.pressBack();
}
}
程式碼中寫了很全的註釋,簡單說下,首先獲取裝置物件和上下文,這個後面要用到,然後啟動測試App,開啟需要測試的介面,上下滑動5次後退出App,由於上文中對API已經有了一定了解,看起程式碼來還是很輕鬆的。
注意:測試方法需要以test開頭,如果存在多個測試方法,以test後的字母順序執行。
程式碼寫完了,接下來就要開始測試了,右擊測試類選擇Run按鈕,或者點選測試類中的執行按鈕進行測試,上面的按鈕代表執行所有測試方法,下面的按鈕代表只執行當前測試方法:
測試執行後,可以看到控制檯上列印了一些資訊:
可以看到,首先通過adb shell命令在裝置中安裝了UiAutomatorDemo和com.yl.uiautomatordemo.test兩個apk,然後啟動測試,此時被測App已經開始執行測試流程,執行完成後,顯示測試結果,看下App的執行效果:
OK,到這裡,UiAutomator的基本用法就講完了。
5.寫在最後
原始碼已託管到GitHub上,歡迎Fork,覺得還不錯就Start一下吧!
歡迎同學們吐槽評論,如果你覺得本篇部落格對你有用,那麼就留個言或者頂一下吧(^-^)