標籤:運行 點擊 商務邏輯 開啟 name word tin 運行時 exception
且說本文之前,還是先說說Android單元測試的意義或者說為什麼我們要進行Android的單元測試?
為什麼要進行單元測試?
單元測試可以協助我們程式員將bug消滅在萌芽期,為後續的整合測試減少時間.大家可以看一下這篇文章,可能會說服你:為什麼要進行煩人的單元測試?
如果那篇文章還不能說服你,那我只能使用殺手鐧了~~
大家可以去各大招聘網站上看看,大部分公司都要求開發人員會編寫測試案例或使用架構或工具進行測試,並且大公司要求更甚.
這下還有什麼好說的嗎?單元測試是一個硬要求,即便你不喜歡單元測試,但是如果你想進入一個理想的公司,這是必備的一個技能,所以無論如何你都要去學習的,反正技多不壓身嘛.
那麼,如果你想學習單元測試,從什麼地方找學習資源呢?
- Android官網(https://developer.android.com/training/testing/start/index.html)
- 官網的中文翻譯,這是一系列文章,同時加了作者自己的見解
- android官網上關於Espresso的一整套教程
- 也可以看我這篇文章來入門
但不管是通過上面哪個途徑,主要說的都是通過Espresso架構進行單元測試.
當然也有其他的一些測試架構,大家也可以去嘗試,但是Espresso架構是google官方大力推薦的一套測試架構,所以無論如何都要學習一下的.另外,自Android Studio2.2版本開始,google就為Espresso架構內建了一個圖形化介面,用來自動產生單元測試代碼.在下一篇文章,我會介紹如何利用這種圖形化介面進行單元測試代碼的編寫.
下面正式開始
首先第一步要做的就是整合Espresso測試環境,非常簡單,在你要測試的Module的gradle裡添加如下兩個依賴:
testCompile ‘junit:junit:4.12‘androidTestCompile ‘com.android.support.test.espresso:espresso-core:2.2.2‘, { exclude group: ‘com.android.support‘, module: ‘support-annotations‘ }
第一個是junit依賴,這個依賴Android Studio一般都會預設配置,所以你只需要配置第二個依賴即可.
舉個栗子:
@RunWith(AndroidJUnit4.class)@LargeTestpublic 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!"))); }}
上面這段代碼是android官網上面的,關於Espresso的原理我就不說了,我也講不來,強行講的話,也講的太膚淺.想瞭解原理的可以去Google一把.
那麼我們首先關注兩個註解:
@Rule:
顧名思義,測試規則,官方的解釋是你可以在該註解下引用一個規則或定義一個方法,而你引用或定義的就是測試規則,這樣說可能不是很清楚,可以看該註解下面的一句話:
public ActivityTestRule mActivityRule = new ActivityTestRule<>( MainActivity.class);
這句話就定義了一個測試規則,可以看到構造方法的參數裡指定了一個 MainActivity.class,具體的體現就是當你運行這段測試代碼時,app將會直接開啟 MainActivity介面然後進行你所定義的測試案例.所以當你想直接測試某個介面時,你可以把那個介面填到這個參數裡,這樣就直接開啟你指定的介面進行測試了.
@Test:
該註解用來定義一個測試案例,當你的測試類別運行時,所執行的代碼就是Test註解下的(Espresso還提供了其他的一些註解,比如:@After,@Before等,具體的用法可以去我上面寫的android官網上查看),當然上面那段代碼對應的就是sayHello測試方法,sayHello方法裡所定義的就是要測試的內容,該內容的含義為:
onView(withText("Say hello!")).perform(click());
含義:根據文本”Say hello!”找個這個控制項然後執行該控制項的點擊方法.
onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));
含義:根據id “textView”找到這個控制項然後檢查該控制項上面顯示的文本是不是”Hello, World!”.
是不是很容易理解?非常語義化,一般都能看的懂.Espresso還提供了其他的方法供我們測試時調用,下面會列舉一些常用的.
但是在列舉常用的方法之前,需要先說明幾點Espresso的注意事項,不然當你測試的時候會因為Espresso報的各種錯誤氣個半死!!!
- 無論是通過withId()找控制項還是通過withText()找控制項或者其他方式比如withClassName(),withResourceName(),withTagKey()等方法,都要一定保證你所找的控制項在當前頁面確實存在且可見,不然會報:NoMatchingViewException,當然你可能還會碰到其他異常,比如AmbiguousViewMatcherException,AppNotIdleException異常等等,具體的報錯原因可以到android官網查看,地址如下:Espresso的各種異常
- 如果你要測試AdapterView ,比如 ListView 或GridView等,使用上面的onView()方法是無效的,因為AdapterView的布局item是動態呈現的,沒法直接指定,所以當你要測試AdapterView時,請把onView()方法換成onData() 方法,與onView()方法返回ViewInteraction類似,onData()方法返回DataInteraction,二者用法基本都是一樣的.
perform()參數中常用的方法:
在上面的一段官網代碼中,我們用到了perform(click()),那麼除了click()方法還有其他功能強大的方法可以供我們使用,下面列舉一些常用的方法:
- click():
返回一個點擊action,Espresso利用這個方法執行一次點擊操作,就和我們自己手動點擊按鈕一樣,只不過Espresso把點擊這個操作自動化了,下面的方法都是一樣的道理,就不再贅述了.
- clearText():
返回一個清除指定view中的文本action,在測試EditText時用的比較多
- swipeLeft():
返回一個從右往左滑動的action,這個在測試ViewPager時特別有用
- swipeRight():
返回一個從左往右滑動的action,這個在測試ViewPager時特別有用
- swipeDown():
返回一個從上往下滑動的action
- swipeUp():
返回一個從下往上滑動的action
- closeSoftKeyboard():
返回一個關閉輸入鍵盤的action
- pressBack():
返回一個點擊手機上返回鍵的action
- doubleClick():
返回一個雙擊action
- longClick():
返回一個長按action
- scrollTo():
返回一個移動action
- replaceText():
返回一個替換文本action
- openLinkWithText():
返回一個開啟指定連結action
除了以上的常用方法還有其他一些不常用的,想繼續研究的可以查看Espresso中的ViewActions類,需要注意的是,所有的方法包括上面說到的和沒說到的,都有一個必須的前提條件,就是你要執行的view必須在當前介面上顯示出來,這有兩層意思:
1,當前介面必須能找到這個控制項
2,這個控制項必須是可見的
這是以上所有方法中通用的要求,當然有些方法還有額外的要求,比如必須要先擷取焦點等,
說到這裡,我們梳理一下我們學習了哪些東西:
1,如何根據id或文本或其他方法找到具體控制項
2,如何讓這個控制項執行相關操作
3,一些使用注意事項
所以,現在我們完全可以自己寫一個完整的測試案例了.
先來個gif圖:
上面的動圖測試的流程為:開啟軟體,滑動Viewpager的3個頁面,在最後一個頁面點擊開始體驗按鈕進入主介面,點擊預約叫車,由於沒有登入所以會跳轉到登陸頁面,輸入手機號,然後點擊擷取驗證碼按鈕,然後輸入驗證碼,最後點擊登陸.
整個流程對應的代碼測試代碼如下:
@LargeTest@RunWith(AndroidJUnit4.class)public class StartActivityTest { @Rule public ActivityTestRule<StartActivity> mActivityTestRule = new ActivityTestRule<>(StartActivity.class); @Test public void startActivityTest() { //根據id找到ViewPager頁面,並判斷是否可見 ViewInteraction appCompatViewPager = onView( allOf(withId(R.id.viewPager), isDisplayed())); // 向左滑動viewpager頁面,下面3句也可以寫成一句話,Espresso會從左至右依次執行 // appCompatViewPager.perform(swipeLeft(),swipeLeft(),swipeLeft()); appCompatViewPager.perform(swipeLeft()); appCompatViewPager.perform(swipeLeft()); appCompatViewPager.perform(swipeLeft()); //根據文本找到"開始體驗"按鈕,並判斷是否可見 ViewInteraction appCompatButton = onView( allOf(withText("開始體驗"), isDisplayed())); //執行按鈕的點擊操作 appCompatButton.perform(click()); //根據控制項的id和該控制項的父布局id找到控制項,並判斷是否可見 ViewInteraction appCompatImageView = onView( allOf(withId(R.id.appointmentCallCar), withParent(withId(R.id.callCarLayout)), isDisplayed())); //執行該控制項的點擊操作 appCompatImageView.perform(click()); //根據id找到控制項,並判斷是否可見 ViewInteraction appCompatEditText = onView( allOf(withId(R.id.phoneNumber), isDisplayed())); //執行替換文本操作,說白了就是輸入文本,輸入完畢之後關閉IME鍵盤 appCompatEditText.perform(replaceText("18894001263"), closeSoftKeyboard()); //根據id和顯示的常值內容找到控制項,並判斷是否可見 ViewInteraction appCompatButton2 = onView( allOf(withId(R.id.getPassword), withText("擷取驗證碼"), isDisplayed())); //執行該控制項的點擊操作 appCompatButton2.perform(click()); //根據id找到控制項,並判斷是否可見 ViewInteraction appCompatEditText2 = onView( allOf(withId(R.id.password), isDisplayed())); //執行替換文本操作,說白了就是輸入文本,輸入完畢之後關閉IME鍵盤 appCompatEditText2.perform(replaceText("2454"), closeSoftKeyboard()); //根據id和顯示的常值內容找到控制項,並判斷是否可見 ViewInteraction appCompatButton3 = onView( allOf(withId(R.id.login), withText("登入"), isDisplayed())); //執行該控制項的點擊操作 appCompatButton3.perform(click()); }}
這裡還需要說明一點,當所有的測試案例執行完畢之後,Espresso會自動關閉介面,根據動圖也可以看到,當點擊完登陸按鈕之後,又回到了系統螢幕介面.
當測試完畢之後,在Android Studio的”Run”控制台可以看到測試結果,如:
如果測試順利通過,會在中左側顯示All Test Passed:
如果測試沒有通過,則會在右側的控制台中輸入錯誤資訊,我們可以根據這些錯誤資訊修改我們的代碼然後再次進行測試.
以上的測試代碼只是測試了啟動和登陸功能,可以看到,套路都是一樣的:根據id或文本等條件找到控制項,然後執行控制項的相關操作,這些代碼都是重複的,唯一變化的就是執行的操作和尋找的條件不一樣,我們試想一下,如果項目一旦很大,我們一個一個手動的編寫測試代碼是不是很麻煩,並且都是一樣的套路,沒有一點技術含量.如果有種方式能自動產生這些測試代碼,而我們只需要根據具體的測試情況修改甚至不改這些自動產生的程式碼就能完成測試,是不是就可以極大的節省我們的時間?而恰好Android Studio2.2版本提供了一個使用Espresso架構進行測試的圖形化介面–Record Espresso Test功能,通過這個功能,我們只需要把軟體運行到真機或模擬器上,然後就可以像平常手動測試軟體一樣,按照商務邏輯點擊/滑動即可,Record Espresso Test功能會自動產生相應的測試代碼,我們運行產生的測試代碼,Espresso就可以自動的按照我們剛才操作的順序自動的完成測試,是不是很方便啊.關於如何使用Record Espresso Test功能,以後會單獨寫一篇文章來說明,其實操作起來也很簡單,大家可以先自己去嘗試一下.
Android自動化測試--Espresso架構使用