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

Android機動車發表於2017-12-17

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

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

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

  • ViewActions:傳送互動事件。

  • ViewAssertions:檢驗測試結果

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


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框架內建了一個圖形化介面,用來自動生成單元測試程式碼。

接下來一起寫一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機動車

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

相關文章