天天看點

Android的UI自動化測試(初識Espresso)

總目錄:Espresso從開始到…

最近因為工作需要開始接觸自動化測試這個陌生的領域,為了了解自動化測試的使用,開始查閱一些關于自動化測試的部落格,在這個過程中也漸漸對它有了興趣,因為它很符合一個原則:

能不動手的絕不動手,“懶”就完事了。

Android自動化測試架構有很多:

Instrumentation、Robotium、Uiautomator、Appium、Selendroid、Espresso

每一種測試架構都在自己所擅長的領域有各自的特點和适用性,且都能很好的完成相應的自動化測試任務,在實際應用中可以根據自己的實際情況進行選擇,在這就不多贅述了。

Espresso

言歸正題,本文主要介紹Google的開源測試架構Espresso。相對于其他架構,它更加的簡潔靈活,上手難度低,對于我這種沒有測試開發基礎的初學者比較友好。

但是,需要注意的一點,Espresso是基于Instrumentation的,是以不能單獨進行跨app的操作。

這種問題作為Android的一把手Google自然也考慮到了。

Google推出的另一個自動化測試架構UIAutomator可以輕松解決跨app測試的問題。

而且,UIAutomator 2.0釋出後,Android Developers blog post所說“最重要的是,UIAutomator現在已經基于Android Instrumentation…”。是以,使用Instrumentation test runner可以運作UIAutomator和Espresso兩種架構,兩者可以在實際開發測試中聯合使用。

特點

Synchronization capabilities

Each time your test invokes onView(), Espresso waits to perform the corresponding UI action or assertion until the following synchronization conditions are met:

  • The message queue is empty.
  • There are no instances of AsyncTask currently executing a task.
  • All developer-defined idling resources are idle.

    By performing these checks, Espresso substantially increases the likelihood that only one UI action or assertion can occur at any given time. This capability gives you more reliable and dependable test results.

在Google的官方文檔介紹中,以上這段描述被放在了最顯眼的位置。簡單的了解:Espresso會在主線程空閑的時候,運作測試代碼(不是絕對的,下文會介紹),盡可能的任意時間内隻進行唯一的操作。

環境配置

作為Google的親兒子,難免會對其照顧有加,相信有一些比較關心版本更新的朋友早已經知道了。在AndroidStudio2.2版本之後,在建立的項目中,AndroidStudio會預設添加Espresso的依賴。

dependencies {
    androidTestCompile('com.android.support.test.espresso:espresso-core:3.0.1', {
        exclude group: 'com.android.support', module: 'support-annotations'
        //不導入依賴中的support-annotations,避免出現依賴沖突,會使用使用者自己導入的包
    })
}
           

預設內建的Espresso包espresso-core及其相關依賴包,足以完成一般性的UI測試,除此之外Espresso還有一些擴充包,用于完成一些特殊的測試場景:

  • espresso-web :包含了對WebView測試的支援資源
  • espresso-idling-resource :Espresso與背景作業同步的機制。(已經包含在core的依賴中)
  • espresso-contrib :包含外部的貢獻DatePicker, RecyclerView以及Drawer行動,交通友善檢查和CountingIdlingResource。
  • espresso-intents :用于密封測試的擴充驗證和存根意圖。
  • espresso-remote- Espresso :多處理功能的位置。

在正式開始進行自動化測試前,需要将裝置的系統動畫關閉,以避免一部分因為動畫切換導緻的控件檢索失敗問題,并且可以極大的減短測試時間。

設定->開發者選項 禁用以下設定 :

  • 視窗動畫縮放
  • 過渡動畫縮放
  • 動畫程式時長縮放

使用方式

Espresso的主要使用方法非常簡單

onView(ViewMatcher)
    .perform(ViewAction)
    .check(ViewAssertion);
           

可以分為三部分進行了解:

  1. 控件查找:Espresso會對目前顯示的界面有序的依次通過ViewMatcher(可以了解為查找條件)進行對比直到檢測到控件符合查找條件(ViewMatcher)的控件。
  2. 控件操作:針對onView提供的控件進行ViewAction操作,為了符合UI操作過程,盡量使用Espresso提供的ViewAction,避免擷取View直接對控件進行相關操作。
  3. 結果校驗:對控件的目前狀态進行校驗。需要注意的是,這裡的校驗一定是針對于某一個确定的控件而言的。

當然僅僅的“控件三部曲”還不足以完成整個自動化測試操作,來讓我們看一個完整的例子。

由于自動化測試需要依賴于app執行,在這裡寫一個Demo作為示例,布局比較簡單就不貼代碼了

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    Button button;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button)findViewById(R.id.btnTest);
        textView = (TextView)findViewById(R.id.tv_content);
        button.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btnTest:
                textView.setVisibility(View.VISIBLE);
                textView.setText("hello espresso!");
                break;
            default:
                break;
        }
    }
}
           

界面中預設有 button 和 textView 兩個控件,其中 textView 預設為 gone,textView 中附帶文本“修改内容”。當點選 button 後,textView的可視狀态修改為 visible ,且 textView 中附帶文本“hello espresso!”

根據界面的具體情況,我們按照如上所述進行自動化測試代碼的編寫。

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
    @Rule
    public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
    @Before
    public void BeforeTest(){
        //TODO: @Before 中的操作将在 @Test 之前進行,通常進行測試前置條件的設定
    }
    @Test
    public void Test(){
        onView(withId(R.id.tv_content))
                .check(matches(not(isDisplayed())));
        onView(withId(R.id.btn01))
                .check(matches(withText("修改内容")))
                .perform(click());
        onView(withId(R.id.tv_content))
                .check(matches(withText("hello espresso!")))
                .check(matches(isDisplayed()));
    }
    @After
    public void AfterTest(){
        //TODO: @After 中的操作将在 @Test 之後進行,通常用于将測試環境回歸初始狀态
    }
}
           

相對于我們正常的代碼編寫,主要的差別就在于 @RunWith @Rule @Before @Test @After

  1. @RunWith

    測試是通過Runner來執行的,這裡我們的測試用例標明一個特定的AndroidJUnit4來執行。

  2. @Rule

    用于設定目前測試啟動的Activity

  3. @Before

    它會在每個測試方法執行前都調用一次,通常進行測試前置條件的設定。

  4. @Test

    說明該方法是測試方法。測試方法必須是public void,可以抛出異常。

  5. @After

    與@Before對應,它會在每個測試方法執行完後都調用一次,通常用于将測試環境回歸初始狀态。

注意

1、Espresso盡量模拟使用者的真實使用,選擇Espresso中自帶的架構函數,不要調用View的方法。

2、盡量避免跨越Activity,每個test在同一個頁面完成。

3、盡量保證test的原子化,任何一個測試都是獨立的。

4、同一個測試類中的相鄰兩個@Test沒有邏輯關系。

5、初次使用某一個Espresso函數時可能會報錯且 Alt+Enter 沒有提示,可以寫完完整一行代碼後再進行嘗試 Alt+Enter 操作。

6、自動化測試失敗後注意錯誤描述以及目前界面的内容介紹

繼續閱讀