最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android利用Espresso進(jìn)行UI自動(dòng)化測(cè)試的方法詳解

 更新時(shí)間:2017年12月18日 11:48:12   作者:安卓干貨營(yíng)  
因?yàn)槲沂歉鉧ndroid開(kāi)發(fā)的,所以被分到了自動(dòng)化測(cè)試小組,所以了解了一些UI自動(dòng)化測(cè)試。下面這篇文章主要給大家介紹了關(guān)于Android利用Espresso進(jìn)行UI自動(dòng)化測(cè)試的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。

為什么需要UI自動(dòng)化測(cè)試?

我有一個(gè)觀點(diǎn),對(duì)于重復(fù)的工作,那么程序都是可以代替的,我想這是作為一個(gè)程序員的一個(gè)基本素養(yǎng)(能偷懶的絕不干活)。UI自動(dòng)化測(cè)試就是為了應(yīng)付一些重復(fù)的工作,比如說(shuō)測(cè)試某個(gè)功能,那么從應(yīng)用點(diǎn)擊,再經(jīng)過(guò)一系列的點(diǎn)擊頁(yè)面才能到達(dá)這個(gè)頁(yè)面,然后進(jìn)行測(cè)試,那么我們是不是可以寫(xiě)段代碼讓app自動(dòng)跑起來(lái),自動(dòng)來(lái)到那個(gè)界面進(jìn)行測(cè)試呢?答案是肯定的,這就是本文所要說(shuō)的自動(dòng)化測(cè)試。

引言

谷歌2013年的時(shí)候開(kāi)源了espress,谷歌的思路是,等到它足夠成熟和穩(wěn)定以后,將其遷移到Android SDK中,以此可見(jiàn)對(duì)他的重視。Google使用Espresso測(cè)試了他們自己的超過(guò)30個(gè)應(yīng)用程序,包括G+、Maps和Drive。

Espresso測(cè)試是非常容易實(shí)現(xiàn)的,由三步構(gòu)成:

  • ViewMachers:尋找用來(lái)測(cè)試的View。
  • ViewActions:發(fā)送交互事件。
  • ViewAssertions:檢驗(yàn)測(cè)試結(jié)果

先看下官方給的示例,就能理解以上的三個(gè)步驟:

onView(withId(R.id.my_view)) // withId(R.id.my_view) is a ViewMatcher  
 .perform(click()) // click() is a ViewAction
 .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion

Espresso框架是google官方大力推薦的一套測(cè)試框架,所以無(wú)論如何都要學(xué)習(xí)一下的.另外,自Android Studio2.2版本開(kāi)始,google就為Espresso框架內(nèi)置了一個(gè)圖形化界面,用來(lái)自動(dòng)生成單元測(cè)試代碼。

接下來(lái)一起寫(xiě)一demo測(cè)試,深入了解Espresso。

準(zhǔn)備

支持Espresso:

dependencies {
 ...
 testCompile 'junit:junit:4.12'
 androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2', {
 exclude group: 'com.android.support', module: 'support-annotations'
 }
}

在dependencies中添加,一般默認(rèn)會(huì)有testCompile 'junit:junit:4.12',所以我們只需添加另一句即可。

defaultConfig{
 ...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

在defaultConfig中添加如上語(yǔ)句,支持測(cè)試運(yùn)行。

創(chuàng)建Test類

特別注意,該類應(yīng)在androidTest文件夾下


  • androidTest:進(jìn)行與Android相關(guān)(如調(diào)用Android設(shè)備等)測(cè)試;
  • test:進(jìn)行簡(jiǎn)單的只涉及java SE相關(guān)的測(cè)試。

舉個(gè)簡(jiǎn)單例子:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {
 @Rule
 public ActivityTestRule mActivityRule = new ActivityTestRule<>(
   MainActivity.class);
 @Test
 public void sayHello(){
  onView(withText("Say hello!")).perform(click());
  onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));
 }
}
  • 首先需要在測(cè)試用例類的類體前添加@RunWith的注解,并設(shè)置測(cè)試運(yùn)行平臺(tái)為AndroidJUnit4
  • 如果允許測(cè)試需要較大消耗,可以使用@LargeTest注解
  • 設(shè)置ActivityTestRule用來(lái)指明被測(cè)試的Activity,使用@Rule注解
  • 測(cè)試方法必須以 test 開(kāi)頭,并且使用@Test注解(否則會(huì)報(bào)找不到方法異常)

@Rule

@Rule
public ActivityTestRule mTestRule = new ActivityTestRule<>(MainActivity.class);

這句話就定義了一個(gè)測(cè)試規(guī)則,可以看到構(gòu)造方法的參數(shù)里指定了一個(gè) MainActivity.class, 具體的體現(xiàn)就是當(dāng)你運(yùn)行這段測(cè)試代碼時(shí),app將會(huì)直接打開(kāi) MainActivity界面然后進(jìn)行你所定義的測(cè)試用例。 所以當(dāng)你想直接測(cè)試某個(gè)界面時(shí),你可以把那個(gè)界面填到這個(gè)參數(shù)里,這樣就直接打開(kāi)你指定的界面進(jìn)行測(cè)試了。

@Test

@Test
public void testLogin() {
 ...
}

定義一個(gè)測(cè)試方法,當(dāng)你的測(cè)試類運(yùn)行時(shí),所執(zhí)行的代碼就是Test注解下的方法(Espresso還提供了其他的一些注解: 比如@After,@Before等,具體的用法可以去我上面寫(xiě)的android官網(wǎng)上查看),當(dāng)然上面那段代碼對(duì)應(yīng)的就是testLogin測(cè)試方法,testLogin方法里所定義的就是要測(cè)試的內(nèi)容。

ViewMachers 查找View

使用onView方法找到view:其中參數(shù)可以是withId(通過(guò)資源id查找),withText(通過(guò)顯示內(nèi)容查找)有多個(gè)約束條件時(shí),可以使用allOf  如allOf(withText("Hello") ,withId(R.id.hello))

注意:

  • 無(wú)論是通過(guò)withId()找控件還是通過(guò)withText()找控件,或者其他方式比如 withClassName() ,withResourceName() ,withTagKey()等方法,都要一定保證你所找的控件在當(dāng)前頁(yè)面確實(shí)存在且可見(jiàn)。
  • 如果要測(cè)試AdapterView ,比如 ListView 或GridView等,使用上面的onView()方法是無(wú)效的,因?yàn)锳dapterView的布局item是動(dòng)態(tài)呈現(xiàn)的,沒(méi)法直接指定,所以當(dāng)要測(cè)試AdapterView時(shí),請(qǐng)把onView()方法換成onData() 方法,與onView()方法返回ViewInteraction類似,onData()方法返回DataInteraction,二者用法基本都是一樣的。

ViewActions 執(zhí)行事件

對(duì)View的操作:perform()方法  方式是onView(...).perform() 。也可以執(zhí)行多個(gè)操作在一個(gè)perform中如:perform(click(),clearText()) 。

所有的操作都有一個(gè)前提 ———— 就是要執(zhí)行的view必須在當(dāng)前界面上顯示出來(lái)(有且可見(jiàn))。

方法名 含義
click() 點(diǎn)擊view
clearText() 清除文本內(nèi)容
swipeLeft() 從右往左滑
swipeRight() 從左往右滑
swipeDown() 從上往下滑
swipeUp() 從下往上滑
click() 點(diǎn)擊view
closeSoftKeyboard() 關(guān)閉軟鍵盤(pán)
pressBack() 按下物理返回鍵
doubleClick() 雙擊
longClick() 長(zhǎng)按
scrollTo() 滾動(dòng)
replaceText() 替換文本
openLinkWithText() 打開(kāi)指定超鏈

ViewAssertions 檢驗(yàn)結(jié)果

使用check()方法來(lái)檢查View是否符合我們的期望: onView(...).check() 檢查view中是否含有文本“hello”              check(matches(withText("hello")))

看下我寫(xiě)的示例

我們基本所有的app都有登錄功能,都需要呼入用戶名和密碼,那么在點(diǎn)擊登錄之前需要對(duì)用戶名和密碼進(jìn)行非空、格式等驗(yàn)證。

以下示例我們點(diǎn)擊登錄按鈕時(shí),首先對(duì)輸入的用戶名和密碼進(jìn)行驗(yàn)證,驗(yàn)證不通過(guò)在TextView上顯示對(duì)應(yīng)原因,驗(yàn)證沒(méi)有問(wèn)題顯示“登錄成功”。

Activity界面及邏輯

 @Override
 public void onClick(View view) {
  if (view.getId() == R.id.bt_login) {
   login();
  }
 }
 /**
  * 去登錄
  */
 private void login() {
  String name = et_name.getText().toString().trim();
  String pwd = et_pwd.getText().toString().trim();
  if (TextUtils.isEmpty(name)) {
   tv_login_result.setText("用戶名為空");
   return;
  }
  if (name.length() < 6 ) {
   tv_login_result.setText("用戶名格式錯(cuò)誤");
   return;
  }
  if (TextUtils.isEmpty(pwd)) {
   tv_login_result.setText("密碼為空");
   return;
  }
  if (pwd.length() < 6 ) {
   tv_login_result.setText("密碼格式錯(cuò)誤");
   return;
  }
  tv_login_result.setText("登錄成功");
 }

其他代碼忽略。

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {
 private String[] names = {"", "a", "123123"};
 private String[] pwds = {"", "a", "123123"};
 @Rule
 public ActivityTestRule mTestRule = new ActivityTestRule<>(MainActivity.class);
 @Before
 public void init() {
  Log.e("TAG", "init: ");
 }
 @Test
 public void testLogin() {
  // 不做任何輸入,直接點(diǎn)擊登錄
  onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
  onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("用戶名為空")));
  // 用戶名是空,點(diǎn)擊登錄
  onView(allOf(withId(R.id.et_name), isDisplayed())).perform(replaceText(names[0]), closeSoftKeyboard());
  onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
  onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("用戶名為空")));
  // 用戶名格式錯(cuò)誤,點(diǎn)擊登錄
  onView(allOf(withId(R.id.et_name), isDisplayed())).perform(replaceText(names[1]), closeSoftKeyboard());
  onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
  onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("用戶名格式錯(cuò)誤")));
  // 用戶名和密碼都正確,點(diǎn)擊登錄
  onView(allOf(withId(R.id.et_name), isDisplayed())).perform(replaceText(names[2]), closeSoftKeyboard());
  onView(allOf(withId(R.id.et_pwd), isDisplayed())).perform(replaceText(pwds[2]), closeSoftKeyboard());
  onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
  onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("登錄成功")));
 }
}

這里我們事先定義了一些測(cè)試數(shù)據(jù),使用Espresso進(jìn)行模擬各種情況輸入和點(diǎn)擊,測(cè)試是否符合我們的預(yù)期:

對(duì)Espresso的介紹大概就是這些了,希望大家多提建議,一起進(jìn)步。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

最新評(píng)論

博乐市| 电白县| 安康市| 巩留县| 义乌市| 九龙城区| 翁牛特旗| 丰顺县| 垫江县| 高雄县| 财经| 德保县| 阳新县| 西畴县| 平顺县| 双柏县| 庆云县| 普安县| 西昌市| 康定县| 曲松县| 淳安县| 丰都县| 沁阳市| 水城县| 泽库县| 望城县| 中方县| 远安县| 舞阳县| 左云县| 大化| 板桥市| 南溪县| 宁德市| 中阳县| 武安市| 辽中县| 福泉市| 蓝田县| 大荔县|