Android使用Espresso進行UI自動化測試

谷歌2013年的時候開源了espress,谷歌的思路是,等到它足夠成熟和穩定之後,將其遷移到Android SDK中,以此可見對他的重視。Google使用Espresso測試了他們本身的超過30個應用程序,包括G+、Maps和Drive。java

Espresso測試是很是容易實現的,由三步構成:android

  • ViewMachers:尋找用來測試的View。bash

  • ViewActions:發送交互事件。微信

  • ViewAssertions:檢驗測試結果app

先看下官方給的示例,就能理解以上的三個步驟:框架

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官方大力推薦的一套測試框架,因此不管如何都要學習一下的.另外,自Android Studio2.2版本開始,google就爲Espresso框架內置了一個圖形化界面,用來自動生成單元測試代碼。ide

接下來一塊兒寫一demo測試,深刻了解Espresso。佈局

準備

支持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中添加,通常默認會有testCompile 'junit:junit:4.12',因此咱們只需添加另外一句便可。學習

defaultConfig{
    ...
	testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
複製代碼

在defaultConfig中添加如上語句,支持測試運行。

建立Test類

特別注意,該類應在androidTest文件夾下

這裏寫圖片描述

  • androidTest:進行與Android相關(如調用Android設備等)測試;
  • test:進行簡單的只涉及java SE相關的測試。

舉個簡單例子:

@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!")));
    }
}
複製代碼
  1. 首先須要在測試用例類的類體前添加@RunWith的註解,並設置測試運行平臺爲AndroidJUnit4
  2. 若是容許測試須要較大消耗,可使用@LargeTest註解
  3. 設置ActivityTestRule用來指明被測試的Activity,使用@Rule註解
  4. 測試方法必須以 test 開頭,而且使用@Test註解(不然會報找不到方法異常)

@Rule

@Rule
public ActivityTestRule mTestRule = new ActivityTestRule<>(MainActivity.class);
複製代碼

這句話就定義了一個測試規則,能夠看到構造方法的參數裏指定了一個 MainActivity.class, 具體的體現就是當你運行這段測試代碼時,app將會直接打開 MainActivity界面而後進行你所定義的測試用例。 因此當你想直接測試某個界面時,你能夠把那個界面填到這個參數裏,這樣就直接打開你指定的界面進行測試了。

@Test

@Test
public void testLogin() {
    ...
}
複製代碼

定義一個測試方法,當你的測試類運行時,所執行的代碼就是Test註解下的方法(Espresso還提供了其餘的一些註解: 好比@After,@Before等,具體的用法能夠去我上面寫的android官網上查看),固然上面那段代碼對應的就是testLogin測試方法,testLogin方法裏所定義的就是要測試的內容。

ViewMachers 查找View

使用onView方法找到view:其中參數能夠是withId(經過資源id查找)withText(經過顯示內容查找)有多個約束條件時,可使用allOf 如allOf(withText("Hello") ,withId(R.id.hello))

注意:

  • 不管是經過withId()找控件仍是經過withText()找控件,或者其餘方式好比 withClassName(),withResourceName(),withTagKey()等方法,都要必定保證你所找的控件在當前頁面確實存在且可見。
  • 若是要測試AdapterView ,好比 ListView 或GridView等,使用上面的onView()方法是無效的,由於AdapterView的佈局item是動態呈現的,無法直接指定,因此當要測試AdapterView時,請把onView()方法換成onData() 方法,與onView()方法返回ViewInteraction相似,onData()方法返回DataInteraction,兩者用法基本都是同樣的。

ViewActions 執行事件

對View的操做:perform()方法 方式是onView(...).perform()。也能夠執行多個操做在一個perform中如:perform(click(),clearText())。

全部的操做都有一個前提 ———— 就是要執行的view必須在當前界面上顯示出來(有且可見)。

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

ViewAssertions 檢驗結果

使用check()方法來檢查View是否符合咱們的指望: onView(...).check() 檢查view中是否含有文本「hello」 check(matches(withText("hello")))

看下我寫的示例

咱們基本全部的app都有登陸功能,都須要呼入用戶名和密碼,那麼在點擊登陸以前須要對用戶名和密碼進行非空、格式等驗證。

如下示例咱們點擊登陸按鈕時,首先對輸入的用戶名和密碼進行驗證,驗證不經過在TextView上顯示對應緣由,驗證沒有問題顯示「登陸成功」。

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("用戶名格式錯誤");
            return;
        }

        if (TextUtils.isEmpty(pwd)) {
            tv_login_result.setText("密碼爲空");
            return;
        }

        if (pwd.length() < 6 ) {
            tv_login_result.setText("密碼格式錯誤");
            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() {

        // 不作任何輸入,直接點擊登陸
        onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
        onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("用戶名爲空")));

        // 用戶名是空,點擊登陸
        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("用戶名爲空")));

        // 用戶名格式錯誤,點擊登陸
        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("用戶名格式錯誤")));

        // 用戶名和密碼都正確,點擊登陸
        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("登陸成功")));
    }
}
複製代碼

這裏咱們事先定義了一些測試數據,使用Espresso進行模擬各類狀況輸入和點擊,測試是否符合咱們的預期:

這裏寫圖片描述

對Espresso的介紹大概就是這些了,但願你們多提建議,一塊兒進步。

獲取更多精彩內容,關注個人微信公衆號——Android機動車

相關文章
相關標籤/搜索