การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso
เขียนการทดสอบส่วนติดต่อผู้ใช้แบบอัตโนมัติด้วย Espresso ค้นหามุมมองด้วย onView() โต้ตอบด้วย perform() ตรวจสอบสถานะด้วย check() และทดสอบการโต้ตอบกับ RecyclerView
การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
Espresso คืออะไร
Espresso คือเฟรมเวิร์กการทดสอบ UI อย่างเป็นทางการของ Android ช่วยให้คุณเขียนการทดสอบที่โต้ตอบกับ UI ของแอปได้ เช่น แตะปุ่ม พิมพ์ข้อความ เลื่อนรายการ และตรวจสอบสิ่งที่แสดงบนหน้าจอ
Espresso ทำงานบนอุปกรณ์หรืออีมูเลเตอร์ (การทดสอบบนอุปกรณ์) และจะประสานกับเธรด UI โดยอัตโนมัติ จึงไม่จำเป็นต้องเรียก sleep() ที่ทำให้การทดสอบไม่แน่นอน
การตั้งค่า
Espresso รวมอยู่ในชุดเครื่องมือทดสอบ Android ให้เพิ่มการพึ่งพาต่อไปนี้ลงใน app/build.gradle:
// app/build.gradle:
android {
defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1' // RecyclerView
}ActivityScenarioRule
ใช้ ActivityScenarioRule เพื่อเปิด Activity ก่อนการทดสอบแต่ละครั้งและปิดหลังการทดสอบ:
@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
@get:Rule
val activityRule = ActivityScenarioRule(LoginActivity::class.java)
@Test
fun `login button is displayed`() {
onView(withId(R.id.btnLogin))
.check(matches(isDisplayed()))
}
}onView() และ ViewMatchers
onView(matcher) ค้นหามุมมองในลำดับชั้นปัจจุบัน รวม matcher เพื่อเพิ่มความแม่นยำ:
// Match by ID:
onView(withId(R.id.tvTitle))
// Match by text:
onView(withText("Submit"))
// Match by content description (for accessibility):
onView(withContentDescription("Close dialog"))
// Combine matchers:
onView(allOf(withId(R.id.btnSave), isEnabled()))
// Inside a specific parent:
onView(withId(R.id.btnSave)).inRoot(isDialog())ViewActions — การโต้ตอบกับมุมมอง
หลังจากค้นหามุมมองแล้ว ให้ดำเนินการด้วย .perform():
// Tap a button:
onView(withId(R.id.btnLogin)).perform(click())
// Type into an EditText:
onView(withId(R.id.etEmail))
.perform(typeText("alice@example.com"), closeSoftKeyboard())
// Clear text and retype:
onView(withId(R.id.etPassword))
.perform(clearText(), typeText("secret123"), closeSoftKeyboard())
// Scroll to a view:
onView(withId(R.id.btnSubmit)).perform(scrollTo(), click())
// Long press:
onView(withId(R.id.ivImage)).perform(longClick())ViewAssertions — การตรวจสอบสถานะ
ตรวจสอบสิ่งที่แสดงบนหน้าจอด้วย .check():
// View is displayed:
onView(withId(R.id.tvError)).check(matches(isDisplayed()))
// View has specific text:
onView(withId(R.id.tvTitle)).check(matches(withText("Welcome!")))
// View is not displayed (GONE or INVISIBLE):
onView(withId(R.id.progressBar)).check(matches(not(isDisplayed())))
// View is enabled:
onView(withId(R.id.btnSave)).check(matches(isEnabled()))
// View does not exist:
onView(withId(R.id.tvError)).check(doesNotExist())การทดสอบการเข้าสู่ระบบฉบับสมบูรณ์
การทดสอบเต็มรูปแบบที่พิมพ์ข้อมูลประจำตัวและแตะปุ่มเข้าสู่ระบบ:
@Test
fun `successful login shows home screen`() {
// Type email
onView(withId(R.id.etEmail))
.perform(typeText("alice@example.com"), closeSoftKeyboard())
// Type password
onView(withId(R.id.etPassword))
.perform(typeText("password123"), closeSoftKeyboard())
// Tap login button
onView(withId(R.id.btnLogin)).perform(click())
// Assert welcome message is shown
onView(withId(R.id.tvWelcome))
.check(matches(withText("Welcome, Alice!")))
}การทดสอบ RecyclerView
ใช้ RecyclerViewActions จาก espresso-contrib เพื่อโต้ตอบกับรายการในลิสต์:
import androidx.test.espresso.contrib.RecyclerViewActions
@Test
fun `clicking item opens detail screen`() {
// Scroll to position 5 and click:
onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
5, click()
))
// Assert detail screen is shown:
onView(withId(R.id.tvDetailTitle)).check(matches(isDisplayed()))
}การทดสอบการตรวจสอบข้อมูลนำเข้า
ตรวจสอบว่าข้อความแสดงข้อผิดพลาดปรากฏขึ้นเมื่อข้อมูลนำเข้าไม่ถูกต้อง:
@Test
fun `empty email shows error message`() {
// Leave email blank, tap login
onView(withId(R.id.btnLogin)).perform(click())
// Assert error is shown
onView(withId(R.id.tilEmail))
.check(matches(hasDescendant(withText("Email is required"))))
}
@Test
fun `short password shows error`() {
onView(withId(R.id.etPassword))
.perform(typeText("123"), closeSoftKeyboard())
onView(withId(R.id.btnLogin)).perform(click())
onView(withId(R.id.tilPassword))
.check(matches(hasDescendant(withText("Minimum 6 characters"))))
}ทรัพยากรตรวจจับการทำงานว่าง
Espresso จะรอให้เธรด UI ว่างโดยอัตโนมัติ แต่จะไม่รอการเรียกเครือข่ายหรือโครูทีน ให้ใช้ IdlingResource เพื่อบอก Espresso ให้รอการทำงานแบบอะซิงโครนัสของคุณ:
// CountingIdlingResource: increment before async work, decrement when done
val idlingResource = CountingIdlingResource("NetworkCall")
// In your ViewModel/Repository:
idlingResource.increment()
viewModelScope.launch {
loadData()
idlingResource.decrement()
}
// In test setUp:
@Before
fun setUp() {
IdlingRegistry.getInstance().register(idlingResource)
}
@After
fun tearDown() {
IdlingRegistry.getInstance().unregister(idlingResource)
}การเรียกใช้การทดสอบ Espresso
เรียกใช้การทดสอบบนอุปกรณ์กับอุปกรณ์หรืออีมูเลเตอร์ที่เชื่อมต่ออยู่:
- ใน Android Studio: คลิกขวาที่คลาสการทดสอบ → เรียกใช้
- ผ่านเทอร์มินัล:
./gradlew connectedAndroidTest - ผลลัพธ์จะปรากฏใน
app/build/reports/androidTests/
ใช้ Android Emulator API 28 ขึ้นไปเพื่อให้การทดสอบเสถียรและรวดเร็ว ปิดแอนิเมชันในการตั้งค่าสำหรับนักพัฒนาเพื่อป้องกันการทดสอบไม่แน่นอน
ตรวจสอบความเข้าใจ
รูปแบบ Espresso ที่ถูกต้องสำหรับค้นหามุมมองและตรวจสอบข้อความคืออะไร
ทบทวน: การทดสอบ UI ด้วย Espresso
การทดสอบ UI แบบอัตโนมัติช่วยค้นหาการถดถอยก่อนที่ผู้ใช้จะพบ:
onView(matcher)— ค้นหามุมมอง.perform(action)— แตะ พิมพ์ และเลื่อน.check(matches(...))— ตรวจสอบการมองเห็น ข้อความ และสถานะRecyclerViewActionsสำหรับการโต้ตอบกับรายการIdlingResourceสำหรับการทำงานแบบอะซิงโครนัส- ปิดแอนิเมชันของระบบเพื่อป้องกันการทดสอบไม่แน่นอน
ถัดไป: ดีบักและวิเคราะห์ประสิทธิภาพแอปของคุณอย่างมืออาชีพ
คำถามที่พบบ่อย
บทเรียน “การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso”
เขียนการทดสอบส่วนติดต่อผู้ใช้แบบอัตโนมัติด้วย Espresso ค้นหามุมมองด้วย onView() โต้ตอบด้วย perform() ตรวจสอบสถานะด้วย check() และทดสอบการโต้ตอบกับ RecyclerView คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม
ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การทดสอบหน่วยด้วย JUnit
- การจำลองด้วย Mockito
- การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso
- การดีบักและการวิเคราะห์ประสิทธิภาพ