您好,登錄后才能下訂單哦!
為什么需要UI自動化測試?
我有一個觀點,對于重復的工作,那么程序都是可以代替的,我想這是作為一個程序員的一個基本素養(能偷懶的絕不干活)。UI自動化測試就是為了應付一些重復的工作,比如說測試某個功能,那么從應用點擊,再經過一系列的點擊頁面才能到達這個頁面,然后進行測試,那么我們是不是可以寫段代碼讓app自動跑起來,自動來到那個界面進行測試呢?答案是肯定的,這就是本文所要說的自動化測試。
引言
谷歌2013年的時候開源了espress,谷歌的思路是,等到它足夠成熟和穩定以后,將其遷移到Android SDK中,以此可見對他的重視。Google使用Espresso測試了他們自己的超過30個應用程序,包括G+、Maps和Drive。
Espresso測試是非常容易實現的,由三步構成:
先看下官方給的示例,就能理解以上的三個步驟:
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文件夾下
舉個簡單例子:
@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!"))); } }
@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))
注意:
withText()
找控件,或者其他方式比如 withClassName()
,withResourceName()
,withTagKey()
等方法,都要一定保證你所找的控件在當前頁面確實存在且可見。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的介紹大概就是這些了,希望大家多提建議,一起進步。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。