เขียนการทดสอบอัตโนมัติด้วย UI Automator (คำแนะนำเดิม)

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

เฟรมเวิร์กการทดสอบ UI Automator เป็น API ที่อิงตามการวัดประสิทธิภาพและทำงานร่วมกับโปรแกรมเรียกใช้การทดสอบ AndroidJUnitRunner เหมาะอย่างยิ่งสำหรับการเขียนการทดสอบอัตโนมัติแบบกล่องดำ ซึ่งโค้ดทดสอบไม่ได้ขึ้นอยู่กับรายละเอียดการใช้งานภายในของแอปเป้าหมาย

ฟีเจอร์หลักของเฟรมเวิร์กการทดสอบ UI Automator มีดังนี้

  • API สำหรับดึงข้อมูลสถานะและดำเนินการกับอุปกรณ์เป้าหมาย โปรดดูข้อมูลเพิ่มเติมที่หัวข้อการเข้าถึงสถานะของอุปกรณ์
  • API ที่รองรับการทดสอบ UI ข้ามแอป ดูข้อมูลเพิ่มเติมได้ที่ UI Automator APIs

การเข้าถึงสถานะอุปกรณ์

เฟรมเวิร์กการทดสอบ UI Automator มีคลาส UiDevice สำหรับเข้าถึงและดำเนินการในอุปกรณ์ที่แอปเป้าหมายทำงานอยู่ คุณสามารถ เรียกใช้เมธอดเพื่อเข้าถึงพร็อพเพอร์ตี้ของอุปกรณ์ เช่น การวางแนวปัจจุบันหรือ ขนาดการแสดงผล นอกจากนี้ คลาส UiDevice ยังช่วยให้คุณทำสิ่งต่อไปนี้ได้ด้วย

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

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

UI Automator API

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

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

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

Kotlin

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()

Java

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 Automator

ก่อนสร้างการทดสอบ UI ด้วย UI Automator ให้ตรวจสอบว่าได้กำหนดค่าตำแหน่งซอร์สโค้ดของการทดสอบและการอ้างอิงโปรเจ็กต์แล้วตามที่อธิบายไว้ในตั้งค่าโปรเจ็กต์ สำหรับการทดสอบ AndroidX

ในbuild.gradle ของโมดูลแอป Android คุณต้องตั้งค่าการอ้างอิงทรัพยากร Dependency ไปยังไลบรารี UI Automator ดังนี้

Kotlin

dependencies { ... androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0") }

Groovy

dependencies { ... androidTestImplementation "androidx.test.uiautomator:uiautomator:2.3.0" }

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

ตรวจสอบ UI บนอุปกรณ์

ก่อนออกแบบการทดสอบ ให้ตรวจสอบคอมโพเนนต์ UI ที่มองเห็นได้ใน อุปกรณ์ หากต้องการให้การทดสอบ UI Automator เข้าถึงคอมโพเนนต์เหล่านี้ได้ ให้ตรวจสอบว่าคอมโพเนนต์เหล่านี้มีป้ายกำกับข้อความที่มองเห็นได้ ค่า android:contentDescription หรือทั้ง 2 อย่าง

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 และกดปุ่มหน้าแรกและปุ่มเมนู

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

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

Kotlin

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
    )
  }
}

Java

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

Kotlin

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()
}

Java

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

Kotlin

val listView: UiObject2 = device.findObject(
    By.clazz("android.widget.ListView")
        .hasChild(
            By.text("Apps")
        )
)

Java

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 หรือเปิดใช้Activity ได้โดยไม่ต้องใช้คำสั่ง Shell เพียงรับออบเจ็กต์ Context ผ่าน getContext()

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

Kotlin

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)
}

Java

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

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

Kotlin

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)
}

Java

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

Kotlin

// Opens the System Settings.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.executeShellCommand("am start -a android.settings.SETTINGS")

Java

// Opens the System Settings.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.executeShellCommand("am start -a android.settings.SETTINGS");

Kotlin

// Opens the notification shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.openNotification()

Java

// Opens the notification shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.openNotification();

Kotlin

// Opens the Quick Settings shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.openQuickSettings()

Java

// Opens the Quick Settings shade.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.openQuickSettings();

Kotlin

// Get the system clock.
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
UiObject2 clock = device.findObject(By.res("com.android.systemui:id/clock"))
print(clock.getText())

Java

// 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() ที่รอการเปลี่ยนผ่าน

Kotlin

@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))
}

Java

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