Espresso 測試框架 - AdapterView



AdapterView 是一種特殊的檢視,專門用於呈現類似資訊的集合,例如從底層資料來源(使用Adapter)獲取的產品列表和使用者聯絡人。資料來源可以是簡單的列表到複雜資料庫條目。一些從AdapterView派生的檢視是ListViewGridViewSpinner

AdapterView根據底層資料來源中可用資料的數量動態呈現使用者介面。此外,AdapterView僅呈現螢幕可見區域內可以呈現的必要最小資料。AdapterView這樣做是為了節省記憶體,並使即使底層資料量很大時,使用者介面也能保持流暢。

分析表明,AdapterView架構的性質使得onView選項及其檢視匹配器變得無關緊要,因為首先可能根本沒有呈現要測試的特定檢視。幸運的是,espresso 提供了一個方法onData(),它接受 Hamcrest 匹配器(與底層資料的型別相關)來匹配底層資料,並返回對應於匹配資料檢視的DataInteraction型別物件。示例程式碼如下所示:

onData(allOf(is(instanceOf(String.class)), startsWith("Apple"))).perform(click())

在這裡,onData()匹配條目“Apple”,如果它在底層資料(陣列列表)中可用,則返回DataInteraction物件以與匹配的檢視(對應於“Apple”條目的 TextView)進行互動。

方法

DataInteraction提供以下方法來與檢視互動:

perform()

這接受檢視操作並觸發傳入的檢視操作。

onData(allOf(is(instanceOf(String.class)), startsWith("Apple"))).perform(click())

check()

這接受檢視斷言並檢查傳入的檢視斷言。

onData(allOf(is(instanceOf(String.class)), startsWith("Apple")))
   .check(matches(withText("Apple")))

inAdapterView()

這接受檢視匹配器。它根據傳入的檢視匹配器選擇特定的AdapterView,並返回DataInteraction物件以與匹配的AdapterView進行互動。

onData(allOf())
   .inAdapterView(withId(R.id.adapter_view))
   .atPosition(5)
   .perform(click())

atPosition()

這接受一個整數型別的引數,並引用專案在底層資料中的位置。它選擇對應於傳入資料位置值的檢視,並返回DataInteraction物件以與匹配的檢視進行互動。如果我們知道底層資料的正確順序,這將非常有用。

onData(allOf())
   .inAdapterView(withId(R.id.adapter_view))
   .atPosition(5)
   .perform(click())

onChildView()

這接受檢視匹配器並匹配特定子檢視內的檢視。例如,我們可以與基於AdapterView的產品列表中的特定專案(如“購買”按鈕)進行互動。

onData(allOf(is(instanceOf(String.class)), startsWith("Apple")))
   .onChildView(withId(R.id.buy_button))
   .perform(click())

編寫示例應用程式

按照以下步驟編寫一個基於AdapterView的簡單應用程式,並使用onData()方法編寫測試用例。

  • 啟動 Android Studio。

  • 如前所述建立新專案,並將其命名為MyFruitApp

  • 使用重構遷移AndroidX選項選單將應用程式遷移到 AndroidX 框架。

  • 刪除主活動中的預設設計並新增ListViewactivity_main.xml的內容如下所示:

<?xml version = "1.0" encoding = "utf-8"?>
<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
   xmlns:app = "http://schemas.android.com/apk/res-auto"
   xmlns:tools = "http://schemas.android.com/tools"
   android:layout_width = "match_parent"
   android:layout_height = "match_parent"
   tools:context = ".MainActivity">
   <ListView
      android:id = "@+id/listView"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content" />
</RelativeLayout>
  • 新增新的佈局資源item.xml以指定列表檢視的專案模板。item.xml的內容如下所示:

<?xml version = "1.0" encoding = "utf-8"?>
<TextView xmlns:android = "http://schemas.android.com/apk/res/android"
   android:id = "@+id/name"
   android:layout_width = "fill_parent"
   android:layout_height = "fill_parent"
   android:padding = "8dp"
/>
  • 現在,建立一個介面卡,其水果陣列作為底層資料,並將其設定為列表檢視。這需要在MainActivityonCreate()中完成,如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   
   // Find fruit list view
   final ListView listView = (ListView) findViewById(R.id.listView);
   
   // Initialize fruit data
   String[] fruits = new String[]{
      "Apple", 
      "Banana", 
      "Cherry", 
      "Dates", 
      "Elderberry", 
      "Fig", 
      "Grapes", 
      "Grapefruit", 
      "Guava",
      "Jack fruit", 
      "Lemon",
      "Mango", 
      "Orange", 
      "Papaya", 
      "Pears", 
      "Peaches", 
      "Pineapple",
      "Plums", 
      "Raspberry",
      "Strawberry", 
      "Watermelon"
   };
   
   // Create array list of fruits
   final ArrayList<String> fruitList = new ArrayList<String>();
   for (int i = 0; i < fruits.length; ++i) {
      fruitList.add(fruits[i]);
   }
   
   // Create Array adapter
   final ArrayAdapter adapter = new ArrayAdapter(this, R.layout.item, fruitList);
   
   // Set adapter in list view
   listView.setAdapter(adapter);
}
  • 現在,編譯程式碼並執行應用程式。我的水果應用程式 (My Fruit App) 的螢幕截圖如下所示:

Compile The Code
  • 現在,開啟ExampleInstrumentedTest.java檔案並新增ActivityTestRule,如下所示:

@Rule
public ActivityTestRule<MainActivity> mActivityRule =
   new ActivityTestRule<MainActivity>(MainActivity.class);

另外,請確保在app/build.gradle中完成了測試配置:

dependencies {
   testImplementation 'junit:junit:4.12'
   androidTestImplementation 'androidx.test:runner:1.1.1'
   androidTestImplementation 'androidx.test:rules:1.1.1'
   androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
  • 新增一個新的測試用例來測試列表檢視,如下所示:

@Test
public void listView_isCorrect() {
   // check list view is visible
   onView(withId(R.id.listView)).check(matches(isDisplayed()));
   onData(allOf(is(instanceOf(String.class)), startsWith("Apple"))).perform(click());
   onData(allOf(is(instanceOf(String.class)), startsWith("Apple")))
      .check(matches(withText("Apple")));
   // click a child item
   onData(allOf())
      .inAdapterView(withId(R.id.listView))
      .atPosition(10)
      .perform(click());
}
  • 最後,使用 Android Studio 的上下文選單執行測試用例,並檢查所有測試用例是否都成功。

廣告
© . All rights reserved.