เขียนการทดสอบอัตโนมัติด้วย UI Automator

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 ยังให้คุณดำเนินการต่อไปนี้ได้ด้วย

  1. เปลี่ยนการหมุนของอุปกรณ์
  2. กดปุ่มฮาร์ดแวร์ เช่น "เพิ่มระดับเสียง"
  3. กดปุ่มย้อนกลับ หน้าแรก หรือเมนู
  4. เปิดหน้าต่างแจ้งเตือน
  5. ถ่ายภาพหน้าจอของหน้าต่างปัจจุบัน

เช่น หากต้องการจำลองการกดปุ่มหน้าแรก ให้เรียกใช้UiDevice.pressHome()วิธีนี้

UI Automator API

UI Automator API ช่วยให้คุณเขียนการทดสอบที่มีประสิทธิภาพได้โดยไม่ต้องทราบรายละเอียดการใช้งานของแอปที่กําหนดเป้าหมาย คุณสามารถใช้ API เหล่านี้เพื่อจับภาพและจัดการคอมโพเนนต์ UI ในแอปหลายแอปได้

  • UiObject2: แสดงองค์ประกอบ UI ที่มองเห็นได้ในอุปกรณ์
  • BySelector: ระบุเกณฑ์การจับคู่องค์ประกอบ UI
  • By: สร้าง BySelector โดยใช้วิธีกระชับ
  • Configurator: ช่วยให้คุณตั้งค่าพารามิเตอร์หลักสําหรับการเรียกใช้การทดสอบ UI Automator ได้

ตัวอย่างเช่น โค้ดต่อไปนี้แสดงวิธีเขียนสคริปต์ทดสอบที่เปิดแอป Gmail ในอุปกรณ์

KotlinJava
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 ดังนี้

KotlinGroovy
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

  1. เปิดแอปเป้าหมายบนอุปกรณ์จริง
  2. เชื่อมต่ออุปกรณ์กับเครื่องสำหรับพัฒนาซอฟต์แวร์
  3. เปิดหน้าต่างเทอร์มินัลและไปที่ไดเรกทอรี <android-sdk>/tools/
  4. เรียกใช้เครื่องมือด้วยคําสั่งนี้
 $ uiautomatorviewer

วิธีดูพร็อพเพอร์ตี้ UI สําหรับแอปพลิเคชัน

  1. ในอินเทอร์เฟซ uiautomatorviewer ให้คลิกปุ่มภาพหน้าจอของอุปกรณ์
  2. วางเมาส์เหนือภาพหน้าจอในแผงด้านซ้ายเพื่อดูคอมโพเนนต์ UI ที่เครื่องมือ uiautomatorviewer ระบุ พร็อพเพอร์ตี้จะแสดงในแผงด้านขวาล่างและลําดับชั้นของเลย์เอาต์ในแผงด้านขวาบน
  3. (ไม่บังคับ) คลิกปุ่มเปิด/ปิดโหนด NAF เพื่อดูคอมโพเนนต์ UI ที่ UI Automator เข้าถึงไม่ได้ อาจมีข้อมูลจํากัดสําหรับคอมโพเนนต์เหล่านี้

ดูข้อมูลเกี่ยวกับคอมโพเนนต์ UI ประเภทต่างๆ ที่ Android มีให้ได้ที่อินเทอร์เฟซผู้ใช้

ตรวจสอบว่าเข้าถึงกิจกรรมได้

เฟรมเวิร์กการทดสอบ UI Automator จะทำงานได้ดีขึ้นในแอปที่ใช้ฟีเจอร์การช่วยเหลือพิเศษของ Android เมื่อใช้องค์ประกอบ UI ประเภท View หรือคลาสย่อยของ View จาก SDK คุณไม่จำเป็นต้องใช้การรองรับการช่วยเหลือพิเศษ เนื่องจากคลาสเหล่านี้ได้ดำเนินการให้คุณแล้ว

อย่างไรก็ตาม แอปบางแอปใช้องค์ประกอบ UI ที่กําหนดเองเพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่สมบูรณ์ยิ่งขึ้น องค์ประกอบดังกล่าวจะไม่รองรับการช่วยเหลือพิเศษโดยอัตโนมัติ หากแอปของคุณมีอินสแตนซ์ของคลาสย่อยของ View ที่ไม่ได้มาจาก SDK โปรดตรวจสอบว่าคุณได้เพิ่มฟีเจอร์การช่วยเหลือพิเศษลงในองค์ประกอบเหล่านี้โดยทำตามขั้นตอนต่อไปนี้

  1. สร้างคลาสที่เฉพาะเจาะจงซึ่งขยายจาก ExploreByTouchHelper
  2. เชื่อมโยงอินสแตนซ์ของคลาสใหม่กับองค์ประกอบ UI ที่กําหนดเองที่เฉพาะเจาะจงโดยเรียกใช้ setAccessibilityDelegate()

ดูคําแนะนําเพิ่มเติมเกี่ยวกับการเพิ่มฟีเจอร์การช่วยเหลือพิเศษลงในองค์ประกอบของมุมมองที่กําหนดเองได้ที่การสร้างมุมมองที่กําหนดเองที่เข้าถึงได้ง่าย ดูข้อมูลเพิ่มเติมเกี่ยวกับแนวทางปฏิบัติแนะนำทั่วไปสำหรับการช่วยเหลือพิเศษใน Android ได้ที่การทำให้แอปเข้าถึงได้ง่ายขึ้น

สร้างคลาสการทดสอบ UI Automator

คุณควรเขียนคลาสทดสอบ UI Automator ในลักษณะเดียวกับคลาสทดสอบ JUnit 4 ดูข้อมูลเพิ่มเติมเกี่ยวกับการสร้างคลาสทดสอบ JUnit 4 และการใช้การยืนยันและคำอธิบายประกอบ JUnit 4 ได้ที่หัวข้อสร้างคลาสการทดสอบ 1 หน่วยแบบมีเครื่องควบคุม

เพิ่มแอตทริบิวต์กำกับ @RunWith(AndroidJUnit4.class) ไว้ที่จุดเริ่มต้นของคําจํากัดความคลาสทดสอบ นอกจากนี้ คุณยังต้องระบุคลาส AndroidJUnitRunner ซึ่งมีให้ใน AndroidX Test เป็นตัวดำเนินการทดสอบเริ่มต้นด้วย ขั้นตอนนี้อธิบายไว้อย่างละเอียดในเรียกใช้การทดสอบ UI Automator บนอุปกรณ์หรือโปรแกรมจำลอง

ใช้รูปแบบการเขียนโปรแกรมต่อไปนี้ในคลาสทดสอบ UI Automator

  1. รับออบเจ็กต์ UiDevice เพื่อเข้าถึงอุปกรณ์ที่ต้องการทดสอบโดยเรียกใช้เมธอด getInstance() และส่งออบเจ็กต์ Instrumentation เป็นอาร์กิวเมนต์
  2. รับออบเจ็กต์ UiObject2 เพื่อเข้าถึงคอมโพเนนต์ UI ที่แสดงบนอุปกรณ์ (เช่น มุมมองปัจจุบันในเบื้องหน้า) โดยการเรียกใช้เมธอด findObject()
  3. จำลองการโต้ตอบของผู้ใช้ที่เฉพาะเจาะจงเพื่อดำเนินการกับคอมโพเนนต์ UI นั้นๆ โดยเรียกใช้เมธอด UiObject2 เช่น เรียกใช้ scrollUntil() เพื่อเลื่อน และ setText() เพื่อแก้ไขช่องข้อความ คุณสามารถเรียกใช้ API ในขั้นตอนที่ 2 และ 3 ซ้ำได้ตามต้องการเพื่อทดสอบการโต้ตอบของผู้ใช้ที่ซับซ้อนมากขึ้นซึ่งเกี่ยวข้องกับคอมโพเนนต์ UI หลายรายการหรือลําดับการกระทําของผู้ใช้
  4. ตรวจสอบว่า UI แสดงสถานะหรือลักษณะการทํางานที่คาดไว้หลังจากการโต้ตอบของผู้ใช้เหล่านี้

ขั้นตอนเหล่านี้จะอธิบายอย่างละเอียดในส่วนด้านล่าง

เข้าถึงคอมโพเนนต์ UI

ออบเจ็กต์ UiDevice เป็นวิธีหลักในการเข้าถึงและจัดการสถานะของอุปกรณ์ ในการทดสอบ คุณสามารถเรียกใช้เมธอด UiDevice เพื่อตรวจสอบสถานะของพร็อพเพอร์ตี้ต่างๆ เช่น การวางแนวปัจจุบันหรือขนาดการแสดงผล การทดสอบสามารถใช้ออบเจ็กต์ UiDevice เพื่อดำเนินการระดับอุปกรณ์ได้ เช่น การบังคับให้อุปกรณ์หมุนในลักษณะหนึ่งๆ การกดปุ่ม D-pad บนฮาร์ดแวร์ และการกดปุ่ม Home และ Menu

เราขอแนะนำให้เริ่มการทดสอบจากหน้าจอหลักของอุปกรณ์ จากหน้าจอหลัก (หรือตำแหน่งเริ่มต้นอื่นๆ ที่คุณเลือกในอุปกรณ์) คุณสามารถเรียกใช้เมธอดที่ UI Automator API มีให้เพื่อเลือกและโต้ตอบกับองค์ประกอบ UI ที่เฉพาะเจาะจง

ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่การทดสอบอาจรับอินสแตนซ์ของ UiDevice และจําลองการกดปุ่ม Home

KotlinJava
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 อินสแตนซ์ที่แสดงปุ่มยกเลิกและปุ่มตกลงในแอป

KotlinJava
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 ย่อยซึ่งมีพร็อพเพอร์ตี้ข้อความ

KotlinJava
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() : คลิกตรงกลางขอบเขตที่มองเห็นได้ขององค์ประกอบ UI
  • drag() : ลากออบเจ็กต์นี้ไปยังพิกัดที่กำหนดเอง
  • setText() : ตั้งค่าข้อความในช่องที่แก้ไขได้หลังจากล้างเนื้อหาของช่อง ในทางกลับกัน เมธอด clear() จะล้างข้อความที่มีอยู่ในช่องที่แก้ไขได้
  • swipe() : ดำเนินการปัดไปทางทิศทางที่ระบุ
  • scrollUntil(): ดำเนินการเลื่อนไปยังทิศทางที่ระบุจนกว่า Condition หรือ EventCondition จะเป็นไปตามเงื่อนไข

เฟรมเวิร์กการทดสอบ UI Automator ช่วยให้คุณส่ง Intent หรือเปิดกิจกรรมได้โดยไม่ต้องใช้คำสั่งเชลล์ โดยรับออบเจ็กต์ Context ผ่าน getContext()

ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่การทดสอบสามารถใช้ Intent เพื่อเปิดแอปที่ทดสอบ วิธีนี้มีประโยชน์เมื่อคุณสนใจทดสอบแอปเครื่องคิดเลขเท่านั้นและไม่สนใจเกี่ยวกับตัวเปิด

KotlinJava
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 ในแอปแสดงผลลัพธ์ตามที่คาดไว้ได้

ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่การทดสอบสามารถค้นหาปุ่มหลายปุ่มในแอปเครื่องคิดเลข คลิกปุ่มเหล่านั้นตามลําดับ แล้วตรวจสอบว่าผลลัพธ์ที่ถูกต้องแสดงขึ้น

KotlinJava
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 สามารถโต้ตอบกับทุกอย่างบนหน้าจอ รวมถึงองค์ประกอบของระบบที่อยู่นอกแอป ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้

KotlinJava
// 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");
KotlinJava
// Opens the notification shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.openNotification()
// Opens the notification shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.openNotification();
KotlinJava
// Opens the Quick Settings shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.openQuickSettings()
// Opens the Quick Settings shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.openQuickSettings();
KotlinJava
// 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());

รอทรานซิชัน

ปิดโหมดห้ามรบกวน
รูปที่ 1 UI Automator ปิดโหมดห้ามรบกวนในอุปกรณ์ทดสอบ

การเปลี่ยนหน้าจออาจใช้เวลาและคาดการณ์ระยะเวลาที่แน่นอนไม่ได้ คุณจึงควรให้ UI Automator รอหลังจากดำเนินการ UI Automator มีวิธีการหลายวิธีดังนี้

ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้ UI Automator เพื่อปิดโหมดห้ามรบกวนในการตั้งค่าระบบโดยใช้เมธอด performActionAndWait() ที่รอการเปลี่ยน

KotlinJava
@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 พื้นฐาน