摘要:附錄自動(dòng)化測(cè)試從入門到入門自動(dòng)化測(cè)試從入門到入門自動(dòng)化測(cè)試從入門到入門入門自動(dòng)化測(cè)試從入門到入門自動(dòng)化測(cè)試從入門到入門的測(cè)試自動(dòng)化測(cè)試從入門到入門會(huì)玩的自動(dòng)化測(cè)試從入門到入門
根據(jù)該系列之前的兩篇文章:Hello Testing和Testing APIs,我們已經(jīng)對(duì)Android自動(dòng)化測(cè)試的整體背景有了一些了解。還記得第一篇文章里我提到過的基本思路么?
把自己當(dāng)成用戶,只關(guān)注我能看到的東西。
這個(gè)思路的意思是在于,我要讓機(jī)器模擬我的測(cè)試過程,那么我就需要針對(duì)那些我(作為用戶)能看到的東西,也就是UI。比如說,我并不關(guān)心某個(gè)網(wǎng)絡(luò)請(qǐng)求返回值的具體數(shù)據(jù)是否正確,我關(guān)心的是我能在UI上看到我希望看到的結(jié)果?;诖耍易龈鱾€(gè)測(cè)試用例的一個(gè)通用的思路就是:
找到某個(gè)元素,做一些操作,檢查結(jié)果。
這里包含了三個(gè)流程:
找元素:找到UI上測(cè)試所針對(duì)的元素;
做操作:給這個(gè)元素做一些操作;
檢查結(jié)果:這個(gè)元素做出了我期望的行為。
再直觀一點(diǎn),我向一個(gè)表單輸入一段文字,那么整個(gè)過程就可以描述為:
找元素:找到EditText;
做操作:向EditText輸入字符串;
檢查結(jié)果:EditText顯示了我輸入的字符串。
以上三個(gè)小步驟實(shí)際上也是我作為用戶在使用一個(gè)APP的時(shí)候所遵循的流程。而我們的測(cè)試也是基本遵循這樣一個(gè)流程的。
Espresso為了實(shí)現(xiàn)我們的自動(dòng)化測(cè)試流程,我們采用Espresso進(jìn)行腳本的編寫。我們需要在build.gradle的dependencies中增加如下依賴:
androidTestCompile "com.android.support.test.espresso:espresso-core:2.2.1"
請(qǐng)注意,在這里我并沒有完整地將build.gradle貼出來,只是貼出來了需要增加的部分。這也就意味著,在第一篇Hello Testing中提到的那些配置也都是必不可少的。
另外,我們還需要一個(gè)叫做hamcrest的庫,用來和Espresso配合使用,因此在build.gradle中添加:
androidTestCompile "org.hamcrest:hamcrest-library:1.3"建一個(gè)Test Case
還記得之前文章中我們提到的那個(gè)AppStartActivity的Test Case么?我們可以在相應(yīng)的目錄下建立我們自己的Test Case了!這里貼一下Espresso官方提供的一個(gè)example:
@RunWith(AndroidJUnit4.class) @LargeTest public class HelloWorldEspressoTest { @Rule public ActivityTestRulemActivityRule = new ActivityTestRule(MainActivity.class); @Test public void listGoesOverTheFold() { onView(withText("Hello world!")).check(matches(isDisplayed())); } }
要運(yùn)行我們的測(cè)試用例,我們可以參照第一篇文章中采用Android Studio的方法,也可以在終端中切換到當(dāng)前項(xiàng)目的路徑下,執(zhí)行如下命令:
./gradlew cAT
其中,cAT意為connectedAndroidTest。
找元素我們現(xiàn)在需要找頁面中對(duì)應(yīng)的元素了!Espresso提供了一個(gè)onView()方法用來尋找UI上指定的元素,該方法定義如下:
public static ViewInteraction onView(final MatcherviewMatcher) {}
這個(gè)方法接收一個(gè)Matcher
當(dāng)我們?cè)趯?shí)現(xiàn)布局的時(shí)候,每個(gè)控件都會(huì)有一些特殊的屬性來確定其唯一性,比如最常用的R.id。Matcher
public static MatcherwithId(final int id) {}
大家可以看到,該方法接收了一個(gè)int類型的入?yún)?,返回了一個(gè)Matcher
onView(withId(id));
我們就能在當(dāng)前頁面找到指定ID所對(duì)應(yīng)的目標(biāo)控件了。
再描述一遍這個(gè)流程以便更清晰:我現(xiàn)在要找一個(gè)R.id為指定id的控件,那么我就從我的這個(gè)id出發(fā),先生成一個(gè)查找匹配條件:withId(id)。然后把這個(gè)條件傳給onView()方法:onView(withId(id)),讓onView()方法根據(jù)這個(gè)條件找到我們想要的那個(gè)控件!實(shí)際上這行代碼也是很符合我們的正常思維,可以讀作:
Find a view with Id of the specific id.
實(shí)際上,Espresso提供了很多方法來讓我們自定義我們的查找條件。比如我們可以通過withText()方法來尋找顯示了指定文案的控件等等。具體支持的Matcher類型可以參考Espresso cheat sheet。
需要提醒大家一點(diǎn)的是,onView()方法在根據(jù)匹配條件進(jìn)行查找時(shí),它的目標(biāo)是找到唯一的一個(gè)目標(biāo)控件。如果我們制定的匹配條件有多個(gè)控件可以匹配(比如復(fù)用了layout的布局,或者顯示相同文字的TextView等),該方法會(huì)拋出一個(gè)AmbiguousViewMatcherException異常,因此我們?cè)跇?gòu)造匹配條件時(shí),一定要確保能查找到的目標(biāo)控件是唯一的。如果單一的匹配條件無法精確地匹配出來唯一的控件,我們可能還需要額外的匹配條件,此時(shí)可以用allOf()方法來進(jìn)行復(fù)合匹配條件的構(gòu)造:
onView(allOf(withId(id), withText(text)))
以上代碼可以查找ID為id同時(shí)顯示的文字內(nèi)容為text的控件。這里需要注意的是,為了保證自動(dòng)化測(cè)試的效率,我們應(yīng)盡可能減少匹配條件的數(shù)量。如果用一個(gè)匹配條件能夠滿足我們的需求,我們也就沒有必要再用allOf()來構(gòu)造復(fù)合匹配條件了。
操作元素找到了目標(biāo)元素,接下來我們?cè)撫槍?duì)該元素做一些操作了!
Espresso提供了如下方法來對(duì)相應(yīng)的元素做操作:
public ViewInteraction perform(final ViewAction... viewActions) {}
該方法定義在ViewInteraction類里面。還記得onView()方法的返回值么?yes,正是一個(gè)ViewInteraction對(duì)象。因此,我們可以在onView()方法找到的元素上直接調(diào)用perform()方法進(jìn)行一系列操作:
onView(withId(id)).perform(click())
如上代碼對(duì)onView()查詢到的元素做了一次點(diǎn)擊的操作。請(qǐng)注意,perform()方法的入?yún)⑹亲冮L參數(shù),也就意味著,我們可以依次對(duì)某個(gè)元素做多個(gè)操作:
onView(withId(id)).perform(click(), replaceText(text), closeSoftKeyboard())
以上代碼對(duì)目標(biāo)元素依次做了點(diǎn)擊、輸入文本、關(guān)閉輸入法鍵盤的操作。這是一個(gè)典型的填寫表單的行為。
檢查結(jié)果到目前為止,我們已經(jīng)能找到元素,也能夠?qū)υ剡M(jìn)行一些操作了!接下來我們需要檢查一下這些操作的結(jié)果是否符合我們的預(yù)期。
Espresso提供了一個(gè)check()方法用來檢測(cè)結(jié)果:
public ViewInteraction check(final ViewAssertion viewAssert) {}
該方法接收了一個(gè)ViewAssertion的入?yún)?,該入?yún)⒌淖饔镁褪菣z查結(jié)果是否符合我們的預(yù)期。一般來說,我們可以調(diào)用如下的方法來自定義一個(gè)ViewAssertion:
public static ViewAssertion matches(final Matcher super View> viewMatcher) {}
這個(gè)方法接收了一個(gè)匹配規(guī)則,然后根據(jù)這個(gè)規(guī)則為我們生成了一個(gè)ViewAssertion對(duì)象!還記得Matcher這個(gè)類型么??!是的,這就是onView()方法的入?yún)?!?shí)際上他們是同一個(gè)類型,其使用方法也是完全一致的。
比如,我想檢查一下指定id的TextView是否按照我的預(yù)期顯示了一段text文本,那么我就可以這樣寫:
onView(withId(id)).check(matches(withText(text)))
簡潔明了。ViewAssertion的支持也可以參照這個(gè)Espresso cheat sheet。
恭喜入門!到目前為止,我們已經(jīng)使用Espresso完成了一個(gè)小的測(cè)試流程。如果你都看懂了,那么恭喜你,你已經(jīng)成功入門,可以寫一些簡單的Test Case了!
那么回過頭來,我們就可以理解本文開頭貼出來的Espresso官網(wǎng)提供的那個(gè)小案例了。在listGoesOverTheFold()方法中,只執(zhí)行了一行代碼:
onView(withText("Hello world!")).check(matches(isDisplayed()));
其意義也已經(jīng)足夠明晰:檢查"Hello world!"是否成功地顯示在了屏幕上。
附錄Android自動(dòng)化測(cè)試-從入門到入門(1) Hello Testing!
Android自動(dòng)化測(cè)試-從入門到入門(2) Testing APIs
Android自動(dòng)化測(cè)試-從入門到入門(3) Espresso入門
Android自動(dòng)化測(cè)試-從入門到入門(4) uiautomatorviewer
Android自動(dòng)化測(cè)試-從入門到入門(5) AdapterView的測(cè)試
Android自動(dòng)化測(cè)試-從入門到入門(6) 會(huì)玩的Espresso
Android自動(dòng)化測(cè)試-從入門到入門(7) UI Automator
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65408.html
摘要:附錄自動(dòng)化測(cè)試從入門到入門自動(dòng)化測(cè)試從入門到入門自動(dòng)化測(cè)試從入門到入門入門自動(dòng)化測(cè)試從入門到入門自動(dòng)化測(cè)試從入門到入門的測(cè)試自動(dòng)化測(cè)試從入門到入門會(huì)玩的自動(dòng)化測(cè)試從入門到入門 之前的文章中,我們介紹了Android自動(dòng)化測(cè)試的一些背景,以及Espresso的基本應(yīng)用。除了之前介紹過的Espresso的相關(guān)用法,Espresso還提供了一些其他的用法,可以讓我們?cè)诓煌瑘?chǎng)景下靈活使用。這篇...
摘要:右下角部分顯示當(dāng)前選中控件的各個(gè)屬性。然后,向這個(gè)中輸入賬號(hào)信息就完成了一個(gè)表單的輸入。我們可以根據(jù)屬性區(qū)域顯示的來進(jìn)行匹配賬號(hào)小總結(jié)所提供的界面簡單,使用方便,對(duì)于我們的自動(dòng)化測(cè)試來說是一個(gè)很好的輔助工具。 我們用如下一行代碼來回顧一下之前介紹過的內(nèi)容: import static android.support.test.espresso.Espresso.onView; impo...
摘要:檢查操作的結(jié)果是否符合預(yù)期。大家在實(shí)際編寫自動(dòng)化測(cè)試腳本時(shí)可以靈活選用。 到目前為止,我們已經(jīng)完成了對(duì)Espresso的介紹。從之前的文章我們可以看到,Espresso對(duì)Android APP的自動(dòng)化測(cè)試提供了一系列非常強(qiáng)大的工具和方法。 現(xiàn)在試想這樣一個(gè)場(chǎng)景:我們?cè)贏PP中有一個(gè)更改頭像的功能,此時(shí)我們需要調(diào)用系統(tǒng)相機(jī)進(jìn)行拍照,然后再回到APP提交拍好的照片。在這種場(chǎng)景下,我們需要從...
閱讀 1761·2021-11-25 09:43
閱讀 1801·2021-11-24 10:41
閱讀 3115·2021-09-27 13:36
閱讀 822·2019-08-30 15:53
閱讀 3584·2019-08-30 15:44
閱讀 874·2019-08-30 14:03
閱讀 2585·2019-08-29 16:38
閱讀 1008·2019-08-29 13:23