Android為自動化測試提供了如下的API供我們使用:
AndroidJUnitRunner: 一個可以用來運(yùn)行JUnit 3和JUnit 4樣式的測試類的Test Runner;
Espresso: 提供了UI測試的API;
UI Automator: 提供了跨APP UI測試的API
AndroidJUnitRunner
AndroidJUnitRunner是一個可以用來運(yùn)行JUnit 3和JUnit 4樣式的測試類的Test Runner,并且同時支持Espresso和UI Automator。這是對于之前的InstrumentationTestRunner的一個升級,如果你去查看Gradle文檔中對于Testing配置的說明,會發(fā)現(xiàn)推薦的Test Runner為InstrumentationTestRunner。InstrumentationTestRunner只支持JUnit 3樣式的測試用例,而我們在寫Android測試用例時應(yīng)該盡可能使用JUnit 4樣式來實(shí)現(xiàn)。
相對于Junit 3, JUnit 4有如下改進(jìn):
測試類不需要再繼承
junit.framework.TestCase類;測試方法名不再需要以
test開頭;可以使用類似
@Test,@Before,@After等注解來管理自己的測試方法;增加了一些
Assert方法;支持對
assert方法的static導(dǎo)入。
Espresso
谷歌13年的時候開源了espress,根據(jù)谷歌官方介紹,Espresso最關(guān)鍵的優(yōu)勢就是它能夠檢測到主線程空閑狀態(tài)的時候,在適當(dāng)?shù)臅r候運(yùn)行測試代碼,這樣就沒必要通過Thread.sleep()去讓主線程睡眠的方式去同步測試。說白了,就是Espresso框架在測試app時,不會通過阻塞主線程去同步UI測試。Espresso更多的用于開發(fā)人員的白盒測試。
Espresso測試是非常容易實(shí)現(xiàn)的,它由三部分組成:
UI測試三部曲

Espresso有三個重要的類
ViewMachers:尋找用來測試的View(匹配器)。
ViewActions:發(fā)送交互事件(界面行為)。
ViewAssertions:檢驗(yàn)測試結(jié)果(界面判斷)。
其中ViewMachers是常常是通過匹配條件來需找UI組件或過濾UI,而ViewAction是來模擬用戶操作界面的行為,ViewAssertions對模擬行為操作的View進(jìn)行變換和結(jié)果驗(yàn)證,其三者關(guān)系如圖所示:
pdf 格式的離線版本在此:espersso-cheat-sheet-2.1.0.pdf

Android Studio中搭建步驟:
首先我們在Android Studio中新建一個項(xiàng)目,取名為EspressoTests,最終目錄結(jié)構(gòu)如下:

在根目錄的 build.gradle 文件中添加下面的引入:
添加testInstrumentationRunner:
為我們的工程指定一個TestInstrumentationRunner,TestInstrumentationRunner是用來跑我們所寫的所有的測試用例的。當(dāng)我們采用test的模式來構(gòu)建工程時,這個Runner便會自動為我們執(zhí)行所有的的測試用例,并且返回相應(yīng)的測試結(jié)果。
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
添加編譯依賴:
dependencies {
androidTestCompile 'com.android.support:support-annotations:23.1.1'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
}
我們在androidTest中創(chuàng)建測試
找元素
我們現(xiàn)在需要找頁面中對應(yīng)的元素了!Espresso提供了一個onView()方法用來尋找UI上指定的元素,該方法定義如下:
public static ViewInteraction onView(final Matcher<View> viewMatcher) {}
這個方法接收一個Matcher<View>類型的入?yún)ⅲ祷匾粋€ViewInteraction對象,其所做的事情就是根據(jù)Matcher<View>所指定的條件,在當(dāng)前UI頁面上尋找符合條件的View,并且把相應(yīng)的View返回出來。這樣說還是比較抽象,我們可以用一個具體的例子加以說明。
當(dāng)我們在實(shí)現(xiàn)布局的時候,每個控件都會有一些特殊的屬性來確定其唯一性,比如最常用的R.id。Matcher<View>支持通過控件的唯一ID來從當(dāng)前頁面上尋找目標(biāo)控件,對應(yīng)的方法為withId(),該方法定義如下:
public static Matcher<View> withId(final int id) {}
大家可以看到,該方法接收了一個int類型的入?yún)?,返回了一個Matcher<View>對象,于是,采用如下寫法:
onView(withId(id));
我們就能在當(dāng)前頁面找到指定ID所對應(yīng)的目標(biāo)控件了。
再描述一遍這個流程以便更清晰:我現(xiàn)在要找一個R.id為指定id的控件,那么我就從我的這個id出發(fā),先生成一個查找匹配條件:withId(id)。然后把這個條件傳給onView()方法:onView(withId(id)),讓onView()方法根據(jù)這個條件找到我們想要的那個控件!實(shí)際上這行代碼也是很符合我們的正常思維,可以讀作:
Find a view with Id of the specific id.
實(shí)際上,Espresso提供了很多方法來讓我們自定義我們的查找條件。比如我們可以通過withText()方法來尋找顯示了指定文案的控件等等。具體支持的Matcher類型可以參考Espresso cheat sheet。
需要提醒大家一點(diǎn)的是,onView()方法在根據(jù)匹配條件進(jìn)行查找時,它的目標(biāo)是找到唯一的一個目標(biāo)控件。如果我們制定的匹配條件有多個控件可以匹配(比如復(fù)用了layout的布局,或者顯示相同文字的TextView等),該方法會拋出一個AmbiguousViewMatcherException異常,因此我們在構(gòu)造匹配條件時,一定要確保能查找到的目標(biāo)控件是唯一的。如果單一的匹配條件無法精確地匹配出來唯一的控件,我們可能還需要額外的匹配條件,此時可以用allOf()方法來進(jìn)行復(fù)合匹配條件的構(gòu)造:
onView(allOf(withId(id), withText(text)))
以上代碼可以查找ID為id同時顯示的文字內(nèi)容為text的控件。這里需要注意的是,為了保證自動化測試的效率,我們應(yīng)盡可能減少匹配條件的數(shù)量。如果用一個匹配條件能夠滿足我們的需求,我們也就沒有必要再用allOf()來構(gòu)造復(fù)合匹配條件了。
操作元素
找到了目標(biāo)元素,接下來我們該針對該元素做一些操作了!
Espresso提供了如下方法來對相應(yīng)的元素做操作:
public ViewInteraction perform(final ViewAction... viewActions) {}
該方法定義在ViewInteraction類里面。還記得onView()方法的返回值么?yes,正是一個ViewInteraction對象。因此,我們可以在onView()方法找到的元素上直接調(diào)用perform()方法進(jìn)行一系列操作:
onView(withId(id)).perform(click())
如上代碼對onView()查詢到的元素做了一次點(diǎn)擊的操作。請注意,perform()方法的入?yún)⑹亲冮L參數(shù),也就意味著,我們可以依次對某個元素做多個操作:
onView(withId(id)).perform(click(), replaceText(text), closeSoftKeyboard())
以上代碼對目標(biāo)元素依次做了點(diǎn)擊、輸入文本、關(guān)閉輸入法鍵盤的操作。這是一個典型的填寫表單的行為。
檢查結(jié)果
到目前為止,我們已經(jīng)能找到元素,也能夠?qū)υ剡M(jìn)行一些操作了!接下來我們需要檢查一下這些操作的結(jié)果是否符合我們的預(yù)期。
Espresso提供了一個check()方法用來檢測結(jié)果:
public ViewInteraction check(final ViewAssertion viewAssert) {}
該方法接收了一個ViewAssertion的入?yún)?,該入?yún)⒌淖饔镁褪菣z查結(jié)果是否符合我們的預(yù)期。一般來說,我們可以調(diào)用如下的方法來自定義一個ViewAssertion:
public static ViewAssertion matches(final Matcher<? super View> viewMatcher) {}
這個方法接收了一個匹配規(guī)則,然后根據(jù)這個規(guī)則為我們生成了一個ViewAssertion對象!還記得Matcher這個類型么?。∈堑?,這就是onView()方法的入?yún)ⅲ?shí)際上他們是同一個類型,其使用方法也是完全一致的。
比如,我想檢查一下指定id的TextView是否按照我的預(yù)期顯示了一段text文本,那么我就可以這樣寫:
onView(withId(id)).check(matches(withText(text)))
簡潔明了。ViewAssertion的支持也可以參照這個Espresso cheat sheet。
UI Automator
UI Automator是谷歌推出的,用于UI自動化測試的工具,也就是普通的手工測試,點(diǎn)擊每個控件元素看看輸出的結(jié)果是否符合預(yù)期。比如登陸界面分別輸入正確和錯誤的用戶名密碼然后點(diǎn)擊登陸按鈕看看是否能否登陸以及是否有錯誤提示等。
注意:UI Automator測試框架是基于instrumentation的API,運(yùn)行在Android JunitRunner 之上,同時UI Automator Test只運(yùn)行在Android 4.3(API level 18)以上版本
UI元素查找---uiautomatorviewer工具
uiautomatorviewer工具位于Android SDK/tools/bin
HierarchyViewer默認(rèn)只能在非加密設(shè)備使用,例如工程機(jī),工程平板或者模擬器。如果要在手機(jī)上使用HierarchyViewer,你需要在你的應(yīng)用中添加一個開源庫View Server
鏈接地址:https://github.com/romainguy/ViewServer
該問題的詳細(xì)原因:為什么HierachyViewer無法連接真機(jī)調(diào)試

待續(xù)吧,我對python熟悉些,這個使用java寫的測試用例,沒有實(shí)際用過,等用過了,有經(jīng)驗(yàn)了,在來寫。。。