Espresso มีกลไกสำหรับเลื่อนหรือดำเนินการกับรายการใดรายการหนึ่ง ซึ่งได้แก่ มุมมองอะแดปเตอร์และมุมมองนักรีไซเคิล
เมื่อจัดการกับรายการ โดยเฉพาะรายการที่สร้างด้วย RecyclerView หรือ
AdapterView มุมมองที่คุณสนใจอาจไม่ได้เปิด
บนหน้าจอเพราะมีเด็กเพียงไม่กี่คนเท่านั้นที่แสดงและ
เป็นการรีไซเคิลขณะที่คุณเลื่อน ใช้เมธอด scrollTo() ไม่ได้ในกรณีนี้
เนื่องจากจำเป็นต้องมีข้อมูลพร็อพเพอร์ตี้อยู่แล้ว
โต้ตอบกับรายการมุมมองรายการของอะแดปเตอร์
แทนที่จะใช้เมธอด onView() ให้เริ่มการค้นหาด้วย onData() และ
ระบุตัวจับคู่กับข้อมูลที่สนับสนุนข้อมูลพร็อพเพอร์ตี้ที่คุณต้องการจับคู่
เอสเพรสโซจะทำงานทั้งหมดเพื่อค้นหาแถวในออบเจ็กต์ Adapter และ
ซึ่งทำให้รายการปรากฏในวิวพอร์ต
จับคู่ข้อมูลโดยใช้ตัวจับคู่มุมมองที่กำหนดเอง
กิจกรรมด้านล่างมี ListView ซึ่งได้รับการสนับสนุนโดย SimpleAdapter
ที่เก็บข้อมูลสำหรับแต่ละแถวในออบเจ็กต์ Map<String, Object>

แต่ละแผนที่มี 2 รายการ ได้แก่ คีย์ "STR" ที่มีสตริง เช่น
"item: x" และคีย์ "LEN" ที่มี Integer ซึ่งแสดงถึง
ความยาวของเนื้อหา เช่น
{"STR" : "item: 0", "LEN": 7}
โค้ดสําหรับการคลิกแถวที่มี "item: 50" ซึ่งมีลักษณะดังนี้
Kotlin
onData(allOf(`is`(instanceOf(Map::class.java)), hasEntry(equalTo("STR"), `is`("item: 50")))).perform(click())
Java
onData(allOf(is(instanceOf(Map.class)), hasEntry(equalTo("STR"), is("item: 50")))) .perform(click());
โปรดทราบว่า Espresso เลื่อนดูรายการโดยอัตโนมัติตามที่ต้องการ
มาแยก Matcher<Object> ภายใน onData() กัน
is(instanceOf(Map.class)) จะจำกัดการค้นหาให้แสดงเฉพาะรายการ
AdapterView ซึ่งได้รับการสนับสนุนโดยออบเจ็กต์ Map
ในกรณีของเรา ข้อความค้นหาด้านนี้ตรงกับแถวของมุมมองรายการทุกแถว แต่เรา คลิกรายการหนึ่งๆ โดยเฉพาะ เราจึงจำกัดการค้นหาให้แคบลงด้วยข้อมูลต่อไปนี้
Kotlin
hasEntry(equalTo("STR"), `is`("item: 50"))
Java
hasEntry(equalTo("STR"), is("item: 50"))
Matcher<String, Object> นี้จะตรงกับแผนที่ใดๆ ที่มีรายการที่มี
คีย์ "STR" และค่า "item: 50" เพราะโค้ดที่ใช้ค้นหา
และเราต้องการนำมาใช้ใหม่ในสถานที่อื่นๆ ลองเขียนบรรทัดที่กำหนดเอง
ตัวจับคู่ withItemContent สำหรับกรณีนี้:
Kotlin
return object : BoundedMatcher<Object, Map>(Map::class.java) { override fun matchesSafely(map: Map): Boolean { return hasEntry(equalTo("STR"), itemTextMatcher).matches(map) } override fun describeTo(description: Description) { description.appendText("with item content: ") itemTextMatcher.describeTo(description) } }
Java
return new BoundedMatcher<Object, Map>(Map.class) { @Override public boolean matchesSafely(Map map) { return hasEntry(equalTo("STR"), itemTextMatcher).matches(map); } @Override public void describeTo(Description description) { description.appendText("with item content: "); itemTextMatcher.describeTo(description); } };
คุณใช้ BoundedMatcher เป็นฐานเนื่องจากเพื่อจับคู่เฉพาะวัตถุประเภท
Map ลบล้างเมธอด matchesSafely() โดยใส่ตัวจับคู่ที่พบ
ก่อนหน้านี้ และจับคู่กับ Matcher<String> ที่คุณสามารถส่งผ่าน
อาร์กิวเมนต์ การดำเนินการนี้จะช่วยให้คุณโทรหา withItemContent(equalTo("foo")) ได้ สำหรับรหัส
มีความกระชับ คุณสามารถสร้างตัวจับคู่อื่นที่เรียก equalTo() และ
ยอมรับออบเจ็กต์ String:
Kotlin
fun withItemContent(expectedText: String): Matcher<Object> { checkNotNull(expectedText) return withItemContent(equalTo(expectedText)) }
Java
public static Matcher<Object> withItemContent(String expectedText) { checkNotNull(expectedText); return withItemContent(equalTo(expectedText)); }
ตอนนี้โค้ดสำหรับคลิกรายการนั้นสามารถทำได้ง่าย:
Kotlin
onData(withItemContent("item: 50")).perform(click())
Java
onData(withItemContent("item: 50")).perform(click());
สำหรับโค้ดทั้งหมดของการทดสอบนี้ โปรดดูที่เมธอด testClickOnItem50()
ภายใน
AdapterViewTest
ชั้นเรียนและ
LongListMatchers ที่กำหนดเองนี้
ตัวจับคู่ใน GitHub
ตรงกับมุมมองย่อยที่เจาะจง
ตัวอย่างด้านบนจะส่งออกการคลิกตรงกลางแถวทั้งแถวของ ListView
แต่หากต้องการดำเนินการกับระดับย่อยที่เจาะจง ตัวอย่างเช่น เรา
ต้องการคลิกคอลัมน์ที่ 2 ของแถว LongListActivity
ซึ่งจะแสดง String.length ของเนื้อหาในคอลัมน์แรก:

เพียงเพิ่มข้อกำหนด onChildView() ลงในการใช้งาน
DataInteraction:
Kotlin
onData(withItemContent("item: 60")) .onChildView(withId(R.id.item_size)) .perform(click())
Java
onData(withItemContent("item: 60")) .onChildView(withId(R.id.item_size)) .perform(click());
โต้ตอบกับรายการในมุมมองของผู้รีไซเคิล
ออบเจ็กต์ RecyclerView รายการทำงานแตกต่างจากออบเจ็กต์ AdapterView รายการ ดังนั้น
ไม่สามารถใช้ onData() เพื่อโต้ตอบกับรายชื่อติดต่อได้
ในการโต้ตอบกับ RecyclerViews โดยใช้ Espresso คุณสามารถใช้
แพ็กเกจ espresso-contrib ซึ่งมีคอลเล็กชัน
RecyclerViewActions
ที่ใช้เลื่อนไปยังตำแหน่งหรือดำเนินการกับรายการต่างๆ ได้
scrollTo()- เลื่อนไปที่มุมมองที่ตรงกัน หากมีscrollToHolder()- เลื่อนไปที่ตัวยึดตำแหน่งการดูที่ตรงกัน (หากมี)scrollToPosition()- เลื่อนไปยังตำแหน่งที่ต้องการactionOnHolderItem()- ดำเนินการดูกับตัวยึดตำแหน่งการดูที่ตรงกันactionOnItem()- ดำเนินการดูในข้อมูลพร็อพเพอร์ตี้ที่ตรงกันactionOnItemAtPosition()- ทำ ViewAction บนข้อมูลพร็อพเพอร์ตี้ที่ตำแหน่งที่เฉพาะเจาะจง
ข้อมูลต่อไปนี้จะแสดงตัวอย่างบางส่วนจาก RecyclerViewSample ตัวอย่าง:
Kotlin
@Test(expected = PerformException::class) fun itemWithText_doesNotExist() { // Attempt to scroll to an item that contains the special text. onView(ViewMatchers.withId(R.id.recyclerView)) .perform( // scrollTo will fail the test if no item matches. RecyclerViewActions.scrollTo( hasDescendant(withText("not in the list")) ) ) }
Java
@Test(expected = PerformException.class) public void itemWithText_doesNotExist() { // Attempt to scroll to an item that contains the special text. onView(ViewMatchers.withId(R.id.recyclerView)) // scrollTo will fail the test if no item matches. .perform(RecyclerViewActions.scrollTo( hasDescendant(withText("not in the list")) )); }
Kotlin
@Test fun scrollToItemBelowFold_checkItsText() { // First, scroll to the position that needs to be matched and click on it. onView(ViewMatchers.withId(R.id.recyclerView)) .perform( RecyclerViewActions.actionOnItemAtPosition( ITEM_BELOW_THE_FOLD, click() ) ) // Match the text in an item below the fold and check that it's displayed. val itemElementText = "${activityRule.activity.resources .getString(R.string.item_element_text)} ${ITEM_BELOW_THE_FOLD.toString()}" onView(withText(itemElementText)).check(matches(isDisplayed())) }
Java
@Test public void scrollToItemBelowFold_checkItsText() { // First, scroll to the position that needs to be matched and click on it. onView(ViewMatchers.withId(R.id.recyclerView)) .perform(RecyclerViewActions.actionOnItemAtPosition(ITEM_BELOW_THE_FOLD, click())); // Match the text in an item below the fold and check that it's displayed. String itemElementText = activityRule.getActivity().getResources() .getString(R.string.item_element_text) + String.valueOf(ITEM_BELOW_THE_FOLD); onView(withText(itemElementText)).check(matches(isDisplayed())); }
Kotlin
@Test fun itemInMiddleOfList_hasSpecialText() { // First, scroll to the view holder using the isInTheMiddle() matcher. onView(ViewMatchers.withId(R.id.recyclerView)) .perform(RecyclerViewActions.scrollToHolder(isInTheMiddle())) // Check that the item has the special text. val middleElementText = activityRule.activity.resources .getString(R.string.middle) onView(withText(middleElementText)).check(matches(isDisplayed())) }
Java
@Test public void itemInMiddleOfList_hasSpecialText() { // First, scroll to the view holder using the isInTheMiddle() matcher. onView(ViewMatchers.withId(R.id.recyclerView)) .perform(RecyclerViewActions.scrollToHolder(isInTheMiddle())); // Check that the item has the special text. String middleElementText = activityRule.getActivity().getResources() .getString(R.string.middle); onView(withText(middleElementText)).check(matches(isDisplayed())); }
แหล่งข้อมูลเพิ่มเติม
หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการใช้รายการ Espresso ในการทดสอบ Android โปรดดู แหล่งข้อมูลต่อไปนี้
ตัวอย่าง
- DataAdapterSample:
แสดงจุดแรกเข้า
onData()ของ Espresso สำหรับรายการและAdapterViewออบเจ็กต์