沒有捕抓不到的獵物,就看你有沒有野心去捕抓;沒有完成不了的事情,就看你有沒有野心去做。 ————《狼道》
目錄
一、前言
很早之前寫過一篇《JUnit單元測試》,比較簡單常用的測試方法。寫的只能算是入門知識也不算很細。後面又用過UI Automator與Espresso,不過都沒好好總結。最近剛好需要重新回顧了一下,順便也做下記錄。UI Automator與Espresso都是Android自動化測試框架,各有優缺點,不過個人相比起來更喜歡後者。這裏就給大家簡單介紹下Espresso,整體大綱如下
二、簡介
(1)是什麼
Espresso是一個非常強大的Android UI測試框架。功能類似於ui Automator,但測試由熟悉被測代碼庫的人來編寫最好。
(2)有什麼用
使用Espresso可模擬用戶操作、檢測數據編寫簡潔、漂亮、可靠的Android UI測試。
(3)怎麼用
1.添加依賴
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
//可選 提供ApplicationProvider.getApplicationContext()
androidTestImplementation 'androidx.test:core:1.2.0'
2.基本使用
//公式:
onView(withId(R.id.greet_button)).perform(ViewAction).check(ViewAssertion);
onData(ObjectMatcher).DataOptions.perform(ViewAction).check(ViewAssertion);
根據下面例子,給大家簡單解釋下這些方法的作用
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {
//啓動Activity 不懂Rule可查閱junit.@Rule類似於@Before
@Rule
public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
@Test
public void mainActivityTest() {
//2.withId()匹配控件(View)id,其它匹配方法可在ViewMatchers類中獲得,如:withText()
Matcher<View> viewMatcher = withId(R.id.xxx);
//1.onView()、onData()是啓動測試的入口 ,通過傳入匹配器(Matcher)獲取ViewInteraction實例來執行一些測試操作
ViewInteraction viewInteraction = onView(viewMatcher);
//3.通過ViewInteraction.perform() 執行操作。操作的方法在 ViewActions中,如:click()點擊
viewInteraction.perform(click());
//5.通過通過ViewInteractions類獲取到viewInteraction對象
ViewAssertion viewAssertion = doesNotExist();//表示不存
ViewAssertions.matches(withText("xxx"));//表示匹配"xxx"等文字內容
//4.通過ViewInteraction.check()執行檢測ViewAssertion對象
viewInteraction.check(viewAssertion);
//簡單寫法: 表示根據ID找到指定控件後執行點擊操作並匹配文本是不是“關閉”內容
onView(withId(R.id.btn_close)).perform(click()).check(matches(withText("關閉")));
//表示根據文本找到指定控件後執行點擊操作並匹配是否可點擊
onView(withText("關閉")).perform(click()).check(matches(isClickable()));
}
}
看了上面例子基本可以操作大部分的控件了,但是仍有個別的控件得需要特殊對待。如ListView
@Test
public void mainActivityTest() {
// ListView 來自https://academy.realm.io/posts/chiu-ki-chan-advanced-android-espresso-testing/
onData(withValue(27)).inAdapterView(withId(R.id.list)).perform(click());
}
//定義匹配器 不瞭解的可以看看這篇https://www.jianshu.com/p/662a07e5e828
public static Matcher<Object> withValue(final int value) {
return new BoundedMatcher<Object, MainActivity.Item>(MainActivity.Item.class) {
@Override public void describeTo(Description description) {
description.appendText("has value" + value);
}
@Override public boolean matchesSafely(MainActivity.Item item) {
return item.toString().equals(String.valueOf(value));
}
};
}
更多特別的使用這裏就不舉例了。寫起來可能有點多
3.基礎知識
①基本組成部分
- Espresso:與視圖交互的入口點(通過onView()和onData())
- ViewMatchers:在當前View層級去匹配指定的View。您可以將其中一個或多個傳遞給onView()方法
- ViewActions:執行Views的某些行爲,如點擊事件
- ViewAssertions:檢查Views的某些狀態,如是否顯示
②執行操作
- 點擊事件:onView(...).perform(click());
- 執行多個操作:onView(...).perform(typeText("Hello"), click());
- 檢查是否匹配文本:onView(...).check(matches(withText("Hello!")));
- 適配器相關操作:onData(allOf(is(instanceOf(String.class)), is("Americano"))).perform(click());
- onView(withId(R.id.spinnertext_simple)).check(matches(withText(containsString("Americano"))));
③獲取控件
- 具有唯一ID:onView(withId(R.id.my_view));
- 具有多個相同ID根據屬性:onView(allOf(withId(R.id.my_view), withText("Hello!")));
- 無法具體匹配情況下:onView(allOf(withId(R.id.my_view), not(withText("Unwanted"))));
注意事項:
- 如果無法使用withText()或withContentDescription()縮小搜索範圍,可以考慮將其視爲可訪問性錯誤
- 使用最不具描述性的匹配器來查找要查找的視圖。不要過度指定,因爲這將迫使框架做更多不必要的工作
- 如果目標視圖位於adapterview(如ListView、GridView或spinner)中,則onView()方法可能無法工作。在這些情況下,應該使用onData()
4.方法介紹
①常用方法:
public void fun(){
1.Espresso類
//測試入口
onData(Matcher<? extends Object> dataMatcher)、onView(Matcher<View> viewMatcher)
//關閉軟鍵盤
closeSoftKeyboard();
//循環主線程,直到應用程序空閒 onIdle();
onIdle(Callable<T> action)
//打開在ActionBar中顯示的溢出菜單
openActionBarOverflowOrOptionsMenu(this);
openContextualActionModeOverflowMenu();
//按下後退按鈕。
pressBack();
//與pressBack()類似,但當Espresso導航到應用程序或測試中的進程之外時,不會拋出異常
pressBackUnconditionally();
//將默認的FailureHandler更改爲給定的
setFailureHandler();
2.ViewMatchers類 與onData、onView配合定位view
//匹配文本
withText(Matcher<String> stringMatcher)
withText(String text)
withText(int resourceId)
//匹配背景
hasBackground(int drawableId)
//匹配子元素數目
hasChildCount(int childCount)
//匹配id
withId(Matcher<Integer> integerMatcher)
withId(int id)
//匹配類名字
withClassName(Matcher<String> classNameMatcher)
//匹配資源名
withResourceName(String name)
//匹配具有焦點、選中狀態、可單擊、顯示狀態
hasFocus()/isChecked()/isClickable()/isDisplayed()
3.ViewActions類 模擬用戶操作 與Espresso.perform(ViewAction... viewActions)
//點擊、雙擊、點擊長按
click()、 doubleClick()、longClick()
//關閉軟鍵盤、滾動視圖
closeSoftKeyboard()、scrollTo()
//向下滑動、向左滑動、向右滑動、向上滑動
swipeDown()、swipeLeft()、swipeRight()、 swipeUp()
//輸入文本
typeText(String stringToBeTyped)
4.ViewAssertions類 斷言
//返回一個斷言,該斷言確保視圖匹配器在層次結構中沒有找到任何匹配的視圖
doesNotExist()
//斷言視圖存在於視圖層次結構中,並由給定的視圖匹配器匹配
matches(Matcher<? super View> viewMatcher)
}
②方法介紹 ③多進程測試 ④無障礙功能檢測 ⑤WebView測試 ⑥基礎代碼封裝
5.錯誤處理
@Before
public void setUp() throws Exception {
//ApplicationProvider需要androidTestImplementation 'androidx.test:core:1.2.0'
setFailureHandler(new
CustomFailureHandler(ApplicationProvider.getApplicationContext()));
}
private static class CustomFailureHandler implements FailureHandler {
private final FailureHandler delegate;
public CustomFailureHandler(Context targetContext) {
delegate = new DefaultFailureHandler(targetContext);
}
@Override
public void handle(Throwable error, Matcher<View> viewMatcher) {
try {
delegate.handle(error, viewMatcher);
} catch (NoMatchingViewException e) {
// throw new MySpecialException(e);
System.out.println("打印異常:"+e.getMessage());
}
}
}
6.自動生成測試用例
注意:在您的測試設備上關閉動畫
①組成部分 1.界面交互 2.View 元素斷言
②生成步驟
1.記錄界面交互
- 依次點擊 Run > Record Espresso Test。
- 在 Run > Select Deployment Target 窗口中,選擇要在哪個設備上記錄測試。
- Record Your Test 窗口將在應用啓動後顯示
2.添加斷言以驗證界面元素
- text is:檢查選定 View 元素的文本內容
- exists:檢查 View 元素是否存在於屏幕上可見的當前 View 層次結構中
- does not exist:檢查 View 元素是否不存在於當前 View 層次結構中
操作步驟:
- 點擊 Add Assertion
- 當前屏幕的佈局將顯示在 Record Your Test 窗口右側的面板中
- 從 Edit assertion 框的第二個下拉菜單中選擇要使用的斷言
- 點擊 Save and Add Another 以再創建一個斷言,或點擊 Save Assertion 以關閉斷言面板
3.保存記錄
- 點擊 Complete Recording。此時將顯示 Pick a test class name for your test 窗口
- Espresso 測試記錄器會根據已啓動 Activity 的名稱在軟件包內爲您的測試提供一個唯一的名稱
- 文件將在 Espresso 測試記錄器生成它後自動打開,Android Studio 將顯示在 IDE 的 Project 窗口中選擇的測試類
最後一點很好用,不想寫代碼的可以好好利用。但是不一定比自己寫的快,只要把基礎代碼封裝好。編寫起來也很快。
三、原理
(4)原理是什麼
因爲是測試方面的框架,所以分析起來對我來說還是有點難度。所以這裏就不獻醜了,網上看到過一篇就推薦給大家,想更詳細瞭解的可以看看https://www.jianshu.com/p/1fb248b77b36
四、總結
(5)優缺點
個人使用過程中與UI Automator做了些對比。
- API接口比較少,代碼簡潔,使用方便,運行速度快
- AS提供可自動生成編碼測試的工具
- 適合由熟悉項目人來編寫,自動生成除外
- 無需主動寫Sleep等待UI事件的執行和UI的繪製
- 運行測試前需關閉動畫
五、內容推薦
六、項目參考
單元測試、UI Automator與Espresso基礎代碼都放在下面的項目中,有興趣的可以看下。
Github:https://github.com/DayorNight/BLCS
apk下載體驗地址:https://www.pgyer.com/BLCS
若您發現文章中存在錯誤或不足的地方,希望您能指出!