การทดสอบ UI จะตรวจสอบความถูกต้องของการแสดงผลและการโต้ตอบขององค์ประกอบอินเทอร์เฟซผู้ใช้ของแอปพลิเคชันมือถือ — ปุ่ม ฟิลด์ข้อความ รายการ และส่วนประกอบการนำทาง แตกต่างจากการทดสอบหน่วยที่ตรวจสอบตรรกะทางธุรกิจ การทดสอบ UI จะจำลองการทำงานของผู้ใช้: การแตะ การปัด การป้อนข้อความ และตรวจสอบการตอบสนองของอินเทอร์เฟส จากการศึกษาของ Android Developers, 2024, การทดสอบ UI ครอบคลุม 70% ของสถานการณ์ผู้ใช้ที่สำคัญ และช่วยตรวจจับข้อบกพร่องของเลย์เอาต์ที่ไม่สามารถเข้าถึงได้ด้วยการตรวจสอบเชิงตรรกะ
ประเด็นสำคัญ
การทดสอบ UI เป็นประเภทของการตรวจสอบอัตโนมัติที่โค้ดทดสอบโต้ตอบกับอินเทอร์เฟซกราฟิกของแอปพลิเคชันเช่นเดียวกับที่ผู้ใช้จริงจะทำ การทดสอบจะค้นหาองค์ประกอบบนหน้าจอ — ปุ่ม ฟิลด์ข้อความ รายการ — ดำเนินการกับมันและตรวจสอบการตอบสนองที่คาดหวังของอินเทอร์เฟส ตัวอย่างเช่น หลังจากป้อนรหัสผ่านที่ไม่ถูกต้อง การทดสอบ UI จะตรวจสอบว่าข้อความแสดงข้อผิดพลาดที่มีข้อความถูกต้องปรากฏบนหน้าจอหรือไม่
ความแตกต่างหลักระหว่างการทดสอบ UI และการทำงานอัตโนมัติประเภทอื่นคือทำงานผ่านชั้นการช่วยเหลือของระบบปฏิบัติการ ไม่ใช่ผ่าน API ภายในของแอปพลิเคชัน ซึ่งหมายความว่าการทดสอบ UI มองเห็นอินเทอร์เฟสเหมือนกับที่ผู้ใช้และโปรแกรมอ่านหน้าจอมองเห็น ด้วยเหตุนี้ การทดสอบ UI จึงตรวจสอบไม่เพียงแต่ฟังก์ชันการทำงาน แต่ยังรวมถึงการเข้าถึงขององค์ประกอบ — การปฏิบัติตามข้อกำหนด WCAG
จากการสำรวจของ JetBrains Developer Ecosystem 2023 พบว่า 58% ของทีมมือถือใช้การทดสอบ UI ในไปป์ไลน์ CI/CD ของตน ความครอบคลุมการทดสอบ UI โดยเฉลี่ยในโครงการเชิงพาณิชย์อยู่ที่ 30–40% ของหน้าจอแอปพลิเคชัน โครงการที่มีการทดสอบ UI ได้รับรีวิวเชิงลบในร้านค้าแอปที่เกี่ยวข้องกับการขัดข้องของอินเทอร์เฟสน้อยลง 25%
ความแตกต่างหลักระหว่างการทดสอบ UI และการทดสอบหน่วยคือระดับของนามธรรม การทดสอบหน่วยทำงานกับคลาสและฟังก์ชันแต่ละรายการที่แยกจากเฟรมเวิร์ก Android หรือ iOS การทดสอบเหล่านี้ทำงานบน JVM (สำหรับ Android) โดยไม่ต้องเริ่มโปรแกรมจำลองและใช้เวลาเป็นมิลลิวินาที การทดสอบ UI ทำงานบนอุปกรณ์จริงหรือโปรแกรมจำลอง โต้ตอบกับบริการของระบบ และใช้เวลาเป็นวินาทีหรือนาทีต่อสถานการณ์
กลุ่มเป้าหมายของการทดสอบก็แตกต่างกัน การทดสอบ UI ตรวจสอบสถานการณ์ผู้ใช้แบบ end-to-end — การลงทะเบียน การสั่งซื้อ การค้นหา การทดสอบหน่วยครอบคลุมตรรกะทางธุรกิจ: การคำนวณ การตรวจสอบ การแปลงข้อมูล การทดสอบ UI ไม่ได้ตรวจสอบความถูกต้องของการคำนวณภาษี — มันตรวจสอบว่ายอดรวมแสดงบนหน้าจอหรือไม่ การคำนวณนั้นได้รับการตรวจสอบโดยการทดสอบหน่วย
ตาม Google Testing Blog (2020) อัตราส่วนการทดสอบที่เหมาะสมที่สุดในโครงการเป็นไปตามกฎพีระมิดการทดสอบ: 70% การทดสอบหน่วย 20% การทดสอบการรวมระบบ และ 10% การทดสอบ UI การละเมิดสัดส่วนนี้เพื่อสนับสนุนการทดสอบ UI จะทำให้เวลาในการดำเนินการเพิ่มขึ้นและชุดทดสอบเปราะบาง เนื่องจากการทดสอบ UI มีความไวต่อการเปลี่ยนแปลงในเลย์เอาต์ของหน้าจอ
สำหรับ Android เฟรมเวิร์กที่โดดเด่นคือ Espresso — ไลบรารีจาก Google ที่สร้างใน AndroidX Test Espresso จะซิงโครไนซ์กับเธรด UI โดยอัตโนมัติ รอให้ภาพเคลื่อนไหวและงานเบื้องหลังเสร็จสมบูรณ์ก่อนดำเนินการตรวจสอบครั้งต่อไป สำหรับ Jetpack Compose จะใช้ส่วนขยาย Compose UI Test ซึ่งทำงานผ่านโหนดเชิงความหมายแทนตัวระบุมุมมองแบบดั้งเดิม
สำหรับ iOS เครื่องมือหลักคือ XCUITest ซึ่งเป็นส่วนหนึ่งของ Xcode การทดสอบเขียนด้วย Swift และใช้ตัวระบุการช่วยเหลือเพื่อค้นหาองค์ประกอบ XCUITest รองรับการบันทึกการทดสอบผ่านฟังก์ชันบันทึกและการรวมระบบกับระบบ CI ผ่าน xcodebuild สำหรับโครงการข้ามแพลตฟอร์ม จะใช้ Appium ซึ่งอิงตามโปรโตคอล WebDriver และอนุญาตให้รันการทดสอบเดียวกันบน Android และ iOS ด้วยการเปลี่ยนแปลงโค้ดเพียงเล็กน้อย
Espresso ทำงานกับระบบมุมมองแบบดั้งเดิมผ่าน onView และตัวระบุ ID ทรัพยากร Compose UI Test ใช้ชั้นเชิงความหมาย ทำให้การทดสอบขึ้นอยู่กับลำดับชั้นของมุมมองน้อยลง ตัวอย่างเช่น การค้นหาปุ่มใน Espresso: onView(withId(R.id.submit)), ใน Compose: onNodeWithTag(“submit”) การทดสอบ Compose จัดการการประกอบใหม่โดยอัตโนมัติและไม่ต้องรอสถานะว่างอย่างชัดแจ้ง
XCUITest ใช้ XCUIApplication เป็นจุดเริ่มต้น องค์ประกอบอินเทอร์เฟสแต่ละรายการจะถูกค้นหาผ่านคุณสมบัติการช่วยเหลือ: accessibilityIdentifier สำหรับการเข้าถึงเชิงโปรแกรมและ accessibilityLabel สำหรับ VoiceOver เฟรมเวิร์กสนับสนุนการบันทึกการทดสอบผ่านฟังก์ชันบันทึกของ Xcode — นักพัฒนาดำเนินการบนโปรแกรมจำลองและ Xcode สร้างโค้ดทดสอบ การทดสอบที่พร้อมใช้งานจะทำงานผ่าน xcodebuild test
Appium อิงตามโปรโตคอล WebDriver และรองรับภาษาใดก็ได้: Java, Python, JavaScript กลยุทธ์การค้นหาองค์ประกอบรวมถึง id, xpath, class name และ accessibility id Appium ต้องติดตั้งเซิร์ฟเวอร์และกำหนดค่า Desired Capabilities — platformName, deviceName, appPackage ทางเลือกคือ Maestro ซึ่งใช้สถานการณ์ YAML และไม่ต้องคอมไพล์โค้ดทดสอบ
มาดูการทดสอบ UI สำหรับสถานการณ์เดียวกัน — การเข้าสู่ระบบแอปพลิเคชัน — บนสามเฟรมเวิร์กที่แตกต่างกัน: Espresso สำหรับ Android, XCUITest สำหรับ iOS และ Appium สำหรับแนวทางข้ามแพลตฟอร์ม สถานการณ์: ป้อนชื่อผู้ใช้และรหัสผ่าน กดปุ่มเข้าสู่ระบบ ตรวจสอบการแสดงข้อความต้อนรับ
การทดสอบ Espresso ใช้ onView เพื่อค้นหาองค์ประกอบตามตัวระบุและ perform เพื่อดำเนินการ วิธีการ check กับ isDisplayed matcher ยืนยันว่าองค์ประกอบมองเห็นได้บนหน้าจอ
@RunWith(AndroidJUnit4::class)
class LoginUiTest {
@Rule
@JvmField
val composeTestRule = createComposeRule()
@Test
fun login_withValidCredentials_showsWelcome() {
composeTestRule
.onNodeWithTag("emailField")
.performTextInput("user@example.com")
composeTestRule
.onNodeWithTag("passwordField")
.performTextInput("secret123")
composeTestRule
.onNodeWithTag("loginButton")
.performClick()
composeTestRule
.onNodeWithText("ยินดีต้อนรับ, ผู้ใช้!")
.assertIsDisplayed()
}
}
XCUITest ใช้ XCUIApplication เพื่อเข้าถึงองค์ประกอบอินเทอร์เฟสผ่านตัวระบุการช่วยเหลือ วิธีการ tap() และ exists ให้การโต้ตอบและการตรวจสอบ
class LoginUITests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
continueAfterFailure = false
app.launch()
}
func testLogin_withValidCredentials_showsWelcome() {
app.textFields["emailField"].tap()
app.textFields["emailField"].typeText("user@example.com")
app.secureTextFields["passwordField"].tap()
app.secureTextFields["passwordField"].typeText("secret123")
app.buttons["loginButton"].tap()
XCTAssertTrue(app.staticTexts["Welcome, User!"].exists)
}
}
หลักการแรก — ใช้ตัวระบุการช่วยเหลือแทนป้ายกำกับข้อความเพื่อค้นหาองค์ประกอบ ข้อความของปุ่มสามารถเปลี่ยนแปลงได้เมื่อแปลเป็นภาษาท้องถิ่น ในขณะที่ตัวระบุยังคงที่ ใน Android คือคุณสมบัติ contentDescription ใน iOS — accessibilityIdentifier วิธีการนี้ทำให้การทดสอบไม่ขึ้นอยู่กับภาษาอินเทอร์เฟสและลดค่าใช้จ่ายในการบำรุงรักษาเมื่อมีการเปลี่ยนแปลงเนื้อหา
หลีกเลี่ยง sleep() และการหน่วงเวลาแบบตายตัว — ใช้กลไกการรอในตัวของเฟรมเวิร์ก Espresso จะรอให้ภาพเคลื่อนไหวและงานเบื้องหลังเสร็จสมบูรณ์โดยอัตโนมัติ XCUITest ให้ XCTAssertTrue พร้อมการหมดเวลา การหยุดชั่วคราวอย่างชัดแจ้งทำให้การทดสอบช้าลงและไม่เสถียรมากขึ้น โดยเฉพาะอย่างยิ่งบนอุปกรณ์ที่ช้าในสภาพแวดล้อม CI
จัดกลุ่มการทดสอบตามความสำคัญ: การทดสอบควัน (3–5 สถานการณ์หลัก) ทำงานในทุกคอมมิต ชุดการทดสอบ UI เต็มรูปแบบทำงานก่อนเผยแพร่ ตาม Google Testing Blog (2022) การทดสอบ UI ที่ใช้เวลามากกว่า 30 นาทีใน CI จะลดความถี่ในการทำงานลง 40% ซึ่งลดประสิทธิภาพในฐานะเครื่องมือตรวจจับการถดถอยตั้งแต่เนิ่น ๆ
การทดสอบ UI มีข้อจำกัดหลายประการ ความไวต่อการเปลี่ยนแปลงเลย์เอาต์: การเปลี่ยนตัวระบุ ลำดับชั้น หรือประเภทขององค์ประกอบทำให้การทดสอบล้มเหลวแม้ฟังก์ชันการทำงานจะไม่เปลี่ยนแปลง วิธีแก้ไขคือใช้รูปแบบ Page Object ซึ่งรวมศูนย์ตัวเลือกองค์ประกอบในคลาสแยกต่างหาก เมื่อเลย์เอาต์เปลี่ยนแปลง จะแก้ไขไฟล์ Page Object เพียงไฟล์เดียว ไม่ใช่การทดสอบหลายสิบรายการ
เวลาในการดำเนินการ: การทำงานบนอุปกรณ์จริงหรือโปรแกรมจำลองใช้เวลานานกว่าการทดสอบหน่วย 10–50 เท่า วิธีแก้ไขคือรันการทดสอบ UI แบบขนานบนหลายอุปกรณ์ผ่าน Firebase Test Lab หรือ AWS Device Farm ความไม่เสถียร (flakiness) เป็นปัญหาทั่วไปของการรัน CI ที่เกิดจากภาพเคลื่อนไหว ความหน่วงของเครือข่าย หรือสถานะของโปรแกรมจำลอง เพื่อต่อสู้กับความไม่เสถียร จะใช้การลองใหม่โดยอัตโนมัติของการทดสอบที่ล้มเหลวและการวิเคราะห์ความเสถียรของแต่ละสถานการณ์การทดสอบ
คำถามที่พบบ่อย
สำหรับหน้าจอทั่วไป 3–5 การทดสอบ UI ก็เพียงพอ: happy path การตรวจสอบข้อผิดพลาด สถานะว่าง การเปลี่ยนแนว และการตรวจสอบการช่วยเหลือ หน้าจอที่ซับซ้อนที่มีหลายสถานะ — แบบฟอร์มคำสั่งซื้อ การตั้งค่า — อาจต้องใช้ 10–15 การทดสอบเพื่อครอบคลุมสถานการณ์หลักอย่างสมบูรณ์
ใช่ Appium และ Maestro อนุญาตให้รันสถานการณ์เดียวกันบนทั้งสองแพลตฟอร์ม อย่างไรก็ตาม เฟรมเวิร์กเนทีฟ — Espresso และ XCUITest — ให้ความเสถียร ความเร็ว และการเข้าถึงคุณสมบัติเฉพาะแพลตฟอร์มที่ดีกว่าซึ่งไม่สามารถใช้ได้ผ่านพร็อกซี WebDriver
สำหรับ Compose จะใช้ไลบรารี Compose UI Test พร้อมตัวจับคู่เชิงความหมาย: onNodeWithText, onNodeWithTag, onNodeWithContentDescription ชั้นเชิงความหมายของ Compose จะสรุปลำดับชั้นของมุมมอง ทำให้การทดสอบเปราะบางน้อยลงเมื่อเทียบกับ Espresso แบบดั้งเดิมสำหรับระบบมุมมอง
การรันการทดสอบ UI พื้นฐานจะดำเนินการบนโปรแกรมจำลองใน CI — รวดเร็วและถูกต้อง การตรวจสอบครั้งสุดท้ายก่อนเผยแพร่ควรดำเนินการบนอุปกรณ์จริงผ่าน Firebase Test Lab เพื่อพิจารณาลักษณะของฮาร์ดแวร์จริง: ความละเอียดที่แตกต่างกัน เวอร์ชัน OS และประสิทธิภาพ
ใช้การทำงานแบบขนานบนหลายอุปกรณ์ ปิดภาพเคลื่อนไหวบนโปรแกรมจำลองผ่านตัวเลือกนักพัฒนา สร้างสถาปัตยกรรมการทดสอบแบบโมดูลาร์ และรันชุดควันในทุกคอมมิต โดยรันการทดสอบการถดถอยเต็มรูปแบบตามกำหนดการหรือก่อนเผยแพร่
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม