UI Automator เป็นเฟรมเวิร์กการทดสอบ UI ที่เหมาะสำหรับการทดสอบ UI ที่ใช้งานได้ข้ามแอปในระบบและแอปที่ติดตั้ง UI Automator API ช่วยให้คุณโต้ตอบกับองค์ประกอบที่มองเห็นได้ในอุปกรณ์ ไม่ว่า Activity
ใดจะอยู่ในโฟกัสก็ตาม คุณจึงดำเนินการต่างๆ ได้ เช่น เปิดเมนูการตั้งค่าหรือตัวเปิดแอปในอุปกรณ์ทดสอบ การทดสอบสามารถค้นหาคอมโพเนนต์ UI โดยใช้ตัวบ่งชี้ที่สะดวก เช่น ข้อความที่แสดงในคอมโพเนนต์นั้นหรือคำอธิบายเนื้อหา
เฟรมเวิร์กการทดสอบ UI Automator เป็น API ที่อิงตามเครื่องมือวัดผลและทํางานร่วมกับโปรแกรมรันทดสอบ AndroidJUnitRunner
เหมาะสําหรับการเขียนการทดสอบอัตโนมัติแบบกล่องทึบ ซึ่งโค้ดทดสอบไม่ได้อาศัยรายละเอียดการติดตั้งใช้งานภายในของแอปเป้าหมาย
ฟีเจอร์หลักของเฟรมเวิร์กการทดสอบ UI Automator มีดังนี้
- API ดึงข้อมูลสถานะและดำเนินการกับอุปกรณ์เป้าหมาย โปรดดูข้อมูลเพิ่มเติมที่หัวข้อการเข้าถึงสถานะของอุปกรณ์
- API ที่รองรับการทดสอบ UI แบบข้ามแอป ดูข้อมูลเพิ่มเติมได้ที่ UI Automator API
การเข้าถึงสถานะอุปกรณ์
เฟรมเวิร์กการทดสอบ UI Automator มีคลาส UiDevice
เพื่อเข้าถึงและดำเนินการในอุปกรณ์ที่แอปเป้าหมายทำงานอยู่ คุณสามารถเรียกใช้เมธอดของคลาสเพื่อเข้าถึงพร็อพเพอร์ตี้ของอุปกรณ์ เช่น การวางแนวปัจจุบันหรือขนาดการแสดงผล นอกจากนี้ คลาส UiDevice
ยังให้คุณดำเนินการต่อไปนี้ได้ด้วย
- เปลี่ยนการหมุนของอุปกรณ์
- กดปุ่มฮาร์ดแวร์ เช่น "เพิ่มระดับเสียง"
- กดปุ่มย้อนกลับ หน้าแรก หรือเมนู
- เปิดหน้าต่างแจ้งเตือน
- ถ่ายภาพหน้าจอของหน้าต่างปัจจุบัน
เช่น หากต้องการจำลองการกดปุ่มหน้าแรก ให้เรียกใช้UiDevice.pressHome()
วิธีนี้
UI Automator API
UI Automator API ช่วยให้คุณเขียนการทดสอบที่มีประสิทธิภาพได้โดยไม่ต้องทราบรายละเอียดการใช้งานของแอปที่กําหนดเป้าหมาย คุณสามารถใช้ API เหล่านี้เพื่อจับภาพและจัดการคอมโพเนนต์ UI ในแอปหลายแอปได้
UiObject2
: แสดงองค์ประกอบ UI ที่มองเห็นได้ในอุปกรณ์BySelector
: ระบุเกณฑ์การจับคู่องค์ประกอบ UIBy
: สร้างBySelector
โดยใช้วิธีกระชับConfigurator
: ช่วยให้คุณตั้งค่าพารามิเตอร์หลักสําหรับการเรียกใช้การทดสอบ UI Automator ได้
ตัวอย่างเช่น โค้ดต่อไปนี้แสดงวิธีเขียนสคริปต์ทดสอบที่เปิดแอป Gmail ในอุปกรณ์
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.pressHome() val gmail: UiObject2 = device.findObject(By.text("Gmail")) // Perform a click and wait until the app is opened. val opened: Boolean = gmail.clickAndWait(Until.newWindow(), 3000) assertThat(opened).isTrue()
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.pressHome(); UiObject2 gmail = device.findObject(By.text("Gmail")); // Perform a click and wait until the app is opened. Boolean opened = gmail.clickAndWait(Until.newWindow(), 3000); assertTrue(opened);
ตั้งค่าเครื่องมือสร้าง UI อัตโนมัติ
ก่อนสร้างการทดสอบ UI ด้วย UI Automator โปรดตรวจสอบว่าได้กำหนดค่าตำแหน่งซอร์สโค้ดทดสอบและข้อกำหนดของโปรเจ็กต์ตามที่อธิบายไว้ในตั้งค่าโปรเจ็กต์สำหรับ AndroidX Test
ในไฟล์ build.gradle
ของโมดูลแอป Android คุณต้องตั้งค่าการอ้างอิง Dependency ไปยังไลบรารี UI Automator ดังนี้
dependencies {
...
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
}
dependencies {
...
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.3.0'
}
หากต้องการเพิ่มประสิทธิภาพการทดสอบ UI Automator คุณควรตรวจสอบคอมโพเนนต์ UI ของแอปเป้าหมายก่อนเพื่อให้แน่ใจว่าเข้าถึงได้ เคล็ดลับการเพิ่มประสิทธิภาพเหล่านี้จะอธิบายไว้ในส่วนถัดไป 2 ส่วน
ตรวจสอบ UI ในอุปกรณ์
ก่อนออกแบบการทดสอบ ให้ตรวจสอบคอมโพเนนต์ UI ที่แสดงในอุปกรณ์ ตรวจสอบว่าคอมโพเนนต์เหล่านี้มีป้ายกำกับข้อความที่มองเห็นได้ ค่า android:contentDescription
หรือทั้ง 2 อย่าง เพื่อให้การทดสอบ UI Automator เข้าถึงคอมโพเนนต์เหล่านี้ได้
เครื่องมือ uiautomatorviewer
มีอินเทอร์เฟซภาพที่สะดวกสําหรับตรวจสอบลําดับชั้นเลย์เอาต์และดูพร็อพเพอร์ตี้ของคอมโพเนนต์ UI ที่มองเห็นได้ในส่วนหน้าของอุปกรณ์ ข้อมูลนี้ช่วยให้คุณสร้างการทดสอบที่ละเอียดยิ่งขึ้นได้โดยใช้ UI Automator เช่น คุณอาจสร้างตัวเลือก UI ที่ตรงกับพร็อพเพอร์ตี้ที่มองเห็นได้
วิธีเปิดเครื่องมือ uiautomatorviewer
- เปิดแอปเป้าหมายบนอุปกรณ์จริง
- เชื่อมต่ออุปกรณ์กับเครื่องสำหรับพัฒนาซอฟต์แวร์
- เปิดหน้าต่างเทอร์มินัลและไปที่ไดเรกทอรี
<android-sdk>/tools/
- เรียกใช้เครื่องมือด้วยคําสั่งนี้
$ uiautomatorviewer
วิธีดูพร็อพเพอร์ตี้ UI สําหรับแอปพลิเคชัน
- ในอินเทอร์เฟซ
uiautomatorviewer
ให้คลิกปุ่มภาพหน้าจอของอุปกรณ์ - วางเมาส์เหนือภาพหน้าจอในแผงด้านซ้ายเพื่อดูคอมโพเนนต์ UI ที่เครื่องมือ
uiautomatorviewer
ระบุ พร็อพเพอร์ตี้จะแสดงในแผงด้านขวาล่างและลําดับชั้นของเลย์เอาต์ในแผงด้านขวาบน - (ไม่บังคับ) คลิกปุ่มเปิด/ปิดโหนด NAF เพื่อดูคอมโพเนนต์ UI ที่ UI Automator เข้าถึงไม่ได้ อาจมีข้อมูลจํากัดสําหรับคอมโพเนนต์เหล่านี้
ดูข้อมูลเกี่ยวกับคอมโพเนนต์ UI ประเภทต่างๆ ที่ Android มีให้ได้ที่อินเทอร์เฟซผู้ใช้
ตรวจสอบว่าเข้าถึงกิจกรรมได้
เฟรมเวิร์กการทดสอบ UI Automator จะทำงานได้ดีขึ้นในแอปที่ใช้ฟีเจอร์การช่วยเหลือพิเศษของ Android เมื่อใช้องค์ประกอบ UI ประเภท View
หรือคลาสย่อยของ View
จาก SDK คุณไม่จำเป็นต้องใช้การรองรับการช่วยเหลือพิเศษ เนื่องจากคลาสเหล่านี้ได้ดำเนินการให้คุณแล้ว
อย่างไรก็ตาม แอปบางแอปใช้องค์ประกอบ UI ที่กําหนดเองเพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่สมบูรณ์ยิ่งขึ้น
องค์ประกอบดังกล่าวจะไม่รองรับการช่วยเหลือพิเศษโดยอัตโนมัติ หากแอปของคุณมีอินสแตนซ์ของคลาสย่อยของ View
ที่ไม่ได้มาจาก SDK โปรดตรวจสอบว่าคุณได้เพิ่มฟีเจอร์การช่วยเหลือพิเศษลงในองค์ประกอบเหล่านี้โดยทำตามขั้นตอนต่อไปนี้
- สร้างคลาสที่เฉพาะเจาะจงซึ่งขยายจาก ExploreByTouchHelper
- เชื่อมโยงอินสแตนซ์ของคลาสใหม่กับองค์ประกอบ UI ที่กําหนดเองที่เฉพาะเจาะจงโดยเรียกใช้ setAccessibilityDelegate()
ดูคําแนะนําเพิ่มเติมเกี่ยวกับการเพิ่มฟีเจอร์การช่วยเหลือพิเศษลงในองค์ประกอบของมุมมองที่กําหนดเองได้ที่การสร้างมุมมองที่กําหนดเองที่เข้าถึงได้ง่าย ดูข้อมูลเพิ่มเติมเกี่ยวกับแนวทางปฏิบัติแนะนำทั่วไปสำหรับการช่วยเหลือพิเศษใน Android ได้ที่การทำให้แอปเข้าถึงได้ง่ายขึ้น
สร้างคลาสการทดสอบ UI Automator
คุณควรเขียนคลาสทดสอบ UI Automator ในลักษณะเดียวกับคลาสทดสอบ JUnit 4 ดูข้อมูลเพิ่มเติมเกี่ยวกับการสร้างคลาสทดสอบ JUnit 4 และการใช้การยืนยันและคำอธิบายประกอบ JUnit 4 ได้ที่หัวข้อสร้างคลาสการทดสอบ 1 หน่วยแบบมีเครื่องควบคุม
เพิ่มแอตทริบิวต์กำกับ @RunWith(AndroidJUnit4.class) ไว้ที่จุดเริ่มต้นของคําจํากัดความคลาสทดสอบ นอกจากนี้ คุณยังต้องระบุคลาส AndroidJUnitRunner ซึ่งมีให้ใน AndroidX Test เป็นตัวดำเนินการทดสอบเริ่มต้นด้วย ขั้นตอนนี้อธิบายไว้อย่างละเอียดในเรียกใช้การทดสอบ UI Automator บนอุปกรณ์หรือโปรแกรมจำลอง
ใช้รูปแบบการเขียนโปรแกรมต่อไปนี้ในคลาสทดสอบ UI Automator
- รับออบเจ็กต์
UiDevice
เพื่อเข้าถึงอุปกรณ์ที่ต้องการทดสอบโดยเรียกใช้เมธอด getInstance() และส่งออบเจ็กต์ Instrumentation เป็นอาร์กิวเมนต์ - รับออบเจ็กต์
UiObject2
เพื่อเข้าถึงคอมโพเนนต์ UI ที่แสดงบนอุปกรณ์ (เช่น มุมมองปัจจุบันในเบื้องหน้า) โดยการเรียกใช้เมธอด findObject() - จำลองการโต้ตอบของผู้ใช้ที่เฉพาะเจาะจงเพื่อดำเนินการกับคอมโพเนนต์ UI นั้นๆ โดยเรียกใช้เมธอด
UiObject2
เช่น เรียกใช้ scrollUntil() เพื่อเลื่อน และ setText() เพื่อแก้ไขช่องข้อความ คุณสามารถเรียกใช้ API ในขั้นตอนที่ 2 และ 3 ซ้ำได้ตามต้องการเพื่อทดสอบการโต้ตอบของผู้ใช้ที่ซับซ้อนมากขึ้นซึ่งเกี่ยวข้องกับคอมโพเนนต์ UI หลายรายการหรือลําดับการกระทําของผู้ใช้ - ตรวจสอบว่า UI แสดงสถานะหรือลักษณะการทํางานที่คาดไว้หลังจากการโต้ตอบของผู้ใช้เหล่านี้
ขั้นตอนเหล่านี้จะอธิบายอย่างละเอียดในส่วนด้านล่าง
เข้าถึงคอมโพเนนต์ UI
ออบเจ็กต์ UiDevice
เป็นวิธีหลักในการเข้าถึงและจัดการสถานะของอุปกรณ์ ในการทดสอบ คุณสามารถเรียกใช้เมธอด UiDevice
เพื่อตรวจสอบสถานะของพร็อพเพอร์ตี้ต่างๆ เช่น การวางแนวปัจจุบันหรือขนาดการแสดงผล
การทดสอบสามารถใช้ออบเจ็กต์ UiDevice
เพื่อดำเนินการระดับอุปกรณ์ได้ เช่น การบังคับให้อุปกรณ์หมุนในลักษณะหนึ่งๆ การกดปุ่ม D-pad บนฮาร์ดแวร์ และการกดปุ่ม Home และ Menu
เราขอแนะนำให้เริ่มการทดสอบจากหน้าจอหลักของอุปกรณ์ จากหน้าจอหลัก (หรือตำแหน่งเริ่มต้นอื่นๆ ที่คุณเลือกในอุปกรณ์) คุณสามารถเรียกใช้เมธอดที่ UI Automator API มีให้เพื่อเลือกและโต้ตอบกับองค์ประกอบ UI ที่เฉพาะเจาะจง
ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่การทดสอบอาจรับอินสแตนซ์ของ UiDevice
และจําลองการกดปุ่ม Home
import org.junit.Before import androidx.test.runner.AndroidJUnit4 import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.By import androidx.test.uiautomator.Until ... private const val BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample" private const val LAUNCH_TIMEOUT = 5000L private const val STRING_TO_BE_TYPED = "UiAutomator" @RunWith(AndroidJUnit4::class) @SdkSuppress(minSdkVersion = 18) class ChangeTextBehaviorTest2 { private lateinit var device: UiDevice @Before fun startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) // Start from the home screen device.pressHome() // Wait for launcher val launcherPackage: String = device.launcherPackageName assertThat(launcherPackage, notNullValue()) device.wait( Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT ) // Launch the app val context = ApplicationProvider.getApplicationContext<Context>() val intent = context.packageManager.getLaunchIntentForPackage( BASIC_SAMPLE_PACKAGE).apply { // Clear out any previous instances addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } context.startActivity(intent) // Wait for the app to appear device.wait( Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT ) } }
import org.junit.Before; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.By; import androidx.test.uiautomator.Until; ... @RunWith(AndroidJUnit4.class) @SdkSuppress(minSdkVersion = 18) public class ChangeTextBehaviorTest { private static final String BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample"; private static final int LAUNCH_TIMEOUT = 5000; private static final String STRING_TO_BE_TYPED = "UiAutomator"; private UiDevice device; @Before public void startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); // Start from the home screen device.pressHome(); // Wait for launcher final String launcherPackage = device.getLauncherPackageName(); assertThat(launcherPackage, notNullValue()); device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); // Launch the app Context context = ApplicationProvider.getApplicationContext(); final Intent intent = context.getPackageManager() .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE); // Clear out any previous instances intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(intent); // Wait for the app to appear device.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT); } }
ในตัวอย่างนี้ คำสั่ง @SdkSuppress(minSdkVersion = 18) จะช่วยให้มั่นใจว่าระบบจะทำการทดสอบในอุปกรณ์ที่ใช้ Android 4.3 (API ระดับ 18) ขึ้นไปเท่านั้น ตามที่เฟรมเวิร์ก UI Automator กำหนด
ใช้เมธอด findObject()
เพื่อดึงข้อมูล UiObject2
ซึ่งแสดงถึงมุมมองที่ตรงกับเกณฑ์ตัวเลือกที่ระบุ คุณนําUiObject2
อินสแตนซ์ที่สร้างไว้ไปใช้ซ้ำในส่วนอื่นๆ ของการทดสอบแอปได้ตามต้องการ
โปรดทราบว่าเฟรมเวิร์กการทดสอบ UI Automator จะค้นหารายการที่ตรงกันในการแสดงผลปัจจุบันทุกครั้งที่การทดสอบใช้อินสแตนซ์ UiObject2
เพื่อคลิกองค์ประกอบ UI หรือค้นหาพร็อพเพอร์ตี้
ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่การทดสอบอาจสร้างUiObject2
อินสแตนซ์ที่แสดงปุ่มยกเลิกและปุ่มตกลงในแอป
val okButton: UiObject2 = device.findObject( By.text("OK").clazz("android.widget.Button") ) // Simulate a user-click on the OK button, if found. if (okButton != null) { okButton.click() }
UiObject2 okButton = device.findObject( By.text("OK").clazz("android.widget.Button") ); // Simulate a user-click on the OK button, if found. if (okButton != null) { okButton.click(); }
ระบุตัวเลือก
หากต้องการเข้าถึงคอมโพเนนต์ UI ที่เฉพาะเจาะจงในแอป ให้ใช้คลาส By
เพื่อสร้างอินสแตนซ์ BySelector
BySelector
แสดงการค้นหาองค์ประกอบที่เฉพาะเจาะจงใน UI ที่แสดง
หากพบองค์ประกอบที่ตรงกันมากกว่า 1 รายการ ระบบจะแสดงผลองค์ประกอบแรกที่ตรงกันในลําดับชั้นเลย์เอาต์เป็น UiObject2
เป้าหมาย เมื่อสร้าง BySelector
คุณสามารถเชื่อมโยงพร็อพเพอร์ตี้หลายรายการเข้าด้วยกันเพื่อปรับแต่งการค้นหาได้ หากไม่พบองค์ประกอบ UI ที่ตรงกัน ระบบจะแสดงผลลัพธ์เป็น null
คุณสามารถใช้เมธอด hasChild()
หรือ hasDescendant()
เพื่อฝังBySelector
หลายอินสแตนซ์ ตัวอย่างเช่น ตัวอย่างโค้ดต่อไปนี้แสดงวิธีที่การทดสอบอาจระบุการค้นหาเพื่อหา ListView
รายการแรกที่มีองค์ประกอบ UI ย่อยซึ่งมีพร็อพเพอร์ตี้ข้อความ
val listView: UiObject2 = device.findObject( By.clazz("android.widget.ListView") .hasChild( By.text("Apps") ) )
UiObject2 listView = device.findObject( By.clazz("android.widget.ListView") .hasChild( By.text("Apps") ) );
การระบุสถานะออบเจ็กต์ในเกณฑ์ตัวเลือกอาจมีประโยชน์ เช่น หากต้องการเลือกรายการองค์ประกอบที่เลือกทั้งหมดเพื่อให้ยกเลิกการเลือกได้ ให้เรียกใช้เมธอด checked()
โดยตั้งค่าอาร์กิวเมนต์เป็น "จริง"
ดำเนินการ
เมื่อการทดสอบได้รับออบเจ็กต์ UiObject2
แล้ว คุณจะเรียกเมธอดในคลาส UiObject2
เพื่อดำเนินการโต้ตอบของผู้ใช้กับคอมโพเนนต์ UI ที่แสดงโดยออบเจ็กต์นั้นได้ คุณสามารถระบุการดำเนินการต่างๆ เช่น
click()
: คลิกตรงกลางขอบเขตที่มองเห็นได้ขององค์ประกอบ UIdrag()
: ลากออบเจ็กต์นี้ไปยังพิกัดที่กำหนดเองsetText()
: ตั้งค่าข้อความในช่องที่แก้ไขได้หลังจากล้างเนื้อหาของช่อง ในทางกลับกัน เมธอดclear()
จะล้างข้อความที่มีอยู่ในช่องที่แก้ไขได้swipe()
: ดำเนินการปัดไปทางทิศทางที่ระบุscrollUntil()
: ดำเนินการเลื่อนไปยังทิศทางที่ระบุจนกว่าCondition
หรือEventCondition
จะเป็นไปตามเงื่อนไข
เฟรมเวิร์กการทดสอบ UI Automator ช่วยให้คุณส่ง Intent หรือเปิดกิจกรรมได้โดยไม่ต้องใช้คำสั่งเชลล์ โดยรับออบเจ็กต์ Context ผ่าน getContext()
ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่การทดสอบสามารถใช้ Intent เพื่อเปิดแอปที่ทดสอบ วิธีนี้มีประโยชน์เมื่อคุณสนใจทดสอบแอปเครื่องคิดเลขเท่านั้นและไม่สนใจเกี่ยวกับตัวเปิด
fun setUp() { ... // Launch a simple calculator app val context = getInstrumentation().context val intent = context.packageManager.getLaunchIntentForPackage(CALC_PACKAGE).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } // Clear out any previous instances context.startActivity(intent) device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT) }
public void setUp() { ... // Launch a simple calculator app Context context = getInstrumentation().getContext(); Intent intent = context.getPackageManager() .getLaunchIntentForPackage(CALC_PACKAGE); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances context.startActivity(intent); device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT); }
ยืนยันผลลัพธ์
InstrumentationTestCase ขยายจาก TestCase คุณจึงใช้เมธอด Assert มาตรฐานของ JUnit เพื่อทดสอบว่าคอมโพเนนต์ UI ในแอปแสดงผลลัพธ์ตามที่คาดไว้ได้
ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่การทดสอบสามารถค้นหาปุ่มหลายปุ่มในแอปเครื่องคิดเลข คลิกปุ่มเหล่านั้นตามลําดับ แล้วตรวจสอบว่าผลลัพธ์ที่ถูกต้องแสดงขึ้น
private const val CALC_PACKAGE = "com.myexample.calc" fun testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(By.res(CALC_PACKAGE, "two")).click() device.findObject(By.res(CALC_PACKAGE, "plus")).click() device.findObject(By.res(CALC_PACKAGE, "three")).click() device.findObject(By.res(CALC_PACKAGE, "equals")).click() // Verify the result = 5 val result: UiObject2 = device.findObject(By.res(CALC_PACKAGE, "result")) assertEquals("5", result.text) }
private static final String CALC_PACKAGE = "com.myexample.calc"; public void testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(By.res(CALC_PACKAGE, "two")).click(); device.findObject(By.res(CALC_PACKAGE, "plus")).click(); device.findObject(By.res(CALC_PACKAGE, "three")).click(); device.findObject(By.res(CALC_PACKAGE, "equals")).click(); // Verify the result = 5 UiObject2 result = device.findObject(By.res(CALC_PACKAGE, "result")); assertEquals("5", result.getText()); }
เรียกใช้การทดสอบ UI Automator บนอุปกรณ์หรือโปรแกรมจำลอง
คุณสามารถเรียกใช้การทดสอบ UI Automator จาก Android Studio หรือจากบรรทัดคำสั่ง อย่าลืมระบุ AndroidJUnitRunner
เป็นเครื่องมือรันไทม์เริ่มต้นในโปรเจ็กต์
ตัวอย่างเพิ่มเติม
โต้ตอบกับ UI ของระบบ
UI Automator สามารถโต้ตอบกับทุกอย่างบนหน้าจอ รวมถึงองค์ประกอบของระบบที่อยู่นอกแอป ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้
// Opens the System Settings. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.executeShellCommand("am start -a android.settings.SETTINGS")
// Opens the System Settings. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.executeShellCommand("am start -a android.settings.SETTINGS");
// Opens the notification shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.openNotification()
// Opens the notification shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.openNotification();
// Opens the Quick Settings shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.openQuickSettings()
// Opens the Quick Settings shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.openQuickSettings();
// Get the system clock. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) UiObject2 clock = device.findObject(By.res("com.android.systemui:id/clock")) print(clock.getText())
// Get the system clock. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); UiObject2 clock = device.findObject(By.res("com.android.systemui:id/clock")); print(clock.getText());
รอทรานซิชัน

การเปลี่ยนหน้าจออาจใช้เวลาและคาดการณ์ระยะเวลาที่แน่นอนไม่ได้ คุณจึงควรให้ UI Automator รอหลังจากดำเนินการ UI Automator มีวิธีการหลายวิธีดังนี้
UiDevice.performActionAndWait(Runnable action, EventCondition<U> condition, long timeout)
: เช่น หากต้องการคลิกปุ่มและรอจนกว่าหน้าต่างใหม่จะปรากฏ ให้เรียกใช้device.performActionAndWait(() -> button.click(), Until.newWindow(), timeout)
UiDevice.wait(Condition<Object, U> condition, long timeout)
: เช่น หากต้องการรอจนกว่าจะมีUiObject2
รายการใดรายการหนึ่งในอุปกรณ์ ให้เรียกใช้device.wait(Until.hasObject(By.text("my_text")), timeout);
UiObject2.wait(@NonNull Condition<Object, U> condition, long timeout)
: เช่น หากต้องการรอจนกว่าช่องทําเครื่องหมายจะได้รับการทําเครื่องหมาย ให้เรียกใช้checkbox.wait(Until.checked(true), timeout);
UiObject2.clickAndWait(@NonNull EventCondition<U> condition, long timeout)
: เช่น หากต้องการคลิกปุ่มและรอจนกว่าหน้าต่างใหม่จะปรากฏ ให้เรียกใช้button.clickAndWait(Until.newWindow(), timeout);
UiObject2.scrollUntil(@NonNull Direction direction, @NonNull Condition<Object, U> condition)
: เช่น หากต้องการเลื่อนลงจนกว่าจะมีออบเจ็กต์ใหม่ปรากฏขึ้น ให้เรียกใช้object.scrollUntil(Direction.DOWN, Until.hasObject(By.text('new_obj')));
UiObject2.scrollUntil(@NonNull Direction direction, @NonNull EventCondition<U> condition)
: เช่น หากต้องการเลื่อนลงไปยังด้านล่าง ให้เรียกใช้object.scrollUntil(Direction.DOWN, Until.scrollFinished(Direction.DOWN));
ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้ UI Automator เพื่อปิดโหมดห้ามรบกวนในการตั้งค่าระบบโดยใช้เมธอด performActionAndWait()
ที่รอการเปลี่ยน
@Test @SdkSuppress(minSdkVersion = 21) @Throws(Exception::class) fun turnOffDoNotDisturb() { device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.performActionAndWait({ try { device.executeShellCommand("am start -a android.settings.SETTINGS") } catch (e: IOException) { throw RuntimeException(e) } }, Until.newWindow(), 1000) // Check system settings has been opened. Assert.assertTrue(device.hasObject(By.pkg("com.android.settings"))) // Scroll the settings to the top and find Notifications button var scrollableObj: UiObject2 = device.findObject(By.scrollable(true)) scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP)) val notificationsButton = scrollableObj.findObject(By.text("Notifications")) // Click the Notifications button and wait until a new window is opened. device.performActionAndWait({ notificationsButton.click() }, Until.newWindow(), 1000) scrollableObj = device.findObject(By.scrollable(true)) // Scroll down until it finds a Do Not Disturb button. val doNotDisturb = scrollableObj.scrollUntil( Direction.DOWN, Until.findObject(By.textContains("Do Not Disturb")) ) device.performActionAndWait({ doNotDisturb.click() }, Until.newWindow(), 1000) // Turn off the Do Not Disturb. val turnOnDoNotDisturb = device.findObject(By.text("Turn on now")) turnOnDoNotDisturb?.click() Assert.assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000)) }
@Test @SdkSuppress(minSdkVersion = 21) public void turnOffDoNotDisturb() throws Exception{ device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.performActionAndWait(() -> { try { device.executeShellCommand("am start -a android.settings.SETTINGS"); } catch (IOException e) { throw new RuntimeException(e); } }, Until.newWindow(), 1000); // Check system settings has been opened. assertTrue(device.hasObject(By.pkg("com.android.settings"))); // Scroll the settings to the top and find Notifications button UiObject2 scrollableObj = device.findObject(By.scrollable(true)); scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP)); UiObject2 notificationsButton = scrollableObj.findObject(By.text("Notifications")); // Click the Notifications button and wait until a new window is opened. device.performActionAndWait(() -> notificationsButton.click(), Until.newWindow(), 1000); scrollableObj = device.findObject(By.scrollable(true)); // Scroll down until it finds a Do Not Disturb button. UiObject2 doNotDisturb = scrollableObj.scrollUntil(Direction.DOWN, Until.findObject(By.textContains("Do Not Disturb"))); device.performActionAndWait(()-> doNotDisturb.click(), Until.newWindow(), 1000); // Turn off the Do Not Disturb. UiObject2 turnOnDoNotDisturb = device.findObject(By.text("Turn on now")); if(turnOnDoNotDisturb != null) { turnOnDoNotDisturb.click(); } assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000)); }
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ UI Automator ในการทดสอบ Android ได้ที่แหล่งข้อมูลต่อไปนี้
เอกสารอ้างอิง
ตัวอย่าง
- BasicSample: ตัวอย่าง UI Automator พื้นฐาน