Viết kiểm thử tự động bằng UI Automator

UI Automator là một khung kiểm thử giao diện người dùng phù hợp với giao diện người dùng có chức năng trên nhiều ứng dụng kiểm thử trên các ứng dụng đã cài đặt và hệ thống. UI Automator API cho phép bạn tương tác cho thấy các phần tử hiển thị trên một thiết bị, bất kể Activity đang ở đâu tiêu điểm để giúp bạn thực hiện các thao tác như mở trình đơn Cài đặt hoặc trình chạy ứng dụng trong thiết bị thử nghiệm. Quy trình kiểm thử của bạn có thể tra cứu một thành phần giao diện người dùng bằng cách sử dụng tên mô tả thuận tiện như văn bản hiển thị trong thành phần đó hoặc mô tả nội dung.

Khung kiểm thử UI Automator là một API dựa trên đo lường và hoạt động bằng trình chạy kiểm thử AndroidJUnitRunner. Rất phù hợp để viết kiểm thử tự động kiểu hộp mờ, trong đó mã kiểm thử không dựa vào nội bộ chi tiết triển khai của ứng dụng mục tiêu.

Sau đây là các tính năng chính của khung kiểm thử UI Automator:

Truy cập vào trạng thái thiết bị

Khung kiểm thử UI Automator cung cấp một lớp UiDevice để truy cập và thực hiện các thao tác trên thiết bị mà ứng dụng đích đang chạy. Bạn có thể gọi phương thức để truy cập vào các thuộc tính của thiết bị như hướng hiện tại hoặc kích thước hiển thị. Lớp UiDevice cũng cho phép bạn thực hiện các thao tác sau hành động:

  1. Thay đổi hướng xoay của thiết bị.
  2. Nhấn các phím phần cứng, chẳng hạn như "tăng âm lượng".
  3. Nhấn các nút Quay lại, Màn hình chính hoặc Trình đơn.
  4. Mở ngăn thông báo.
  5. Chụp ảnh màn hình của cửa sổ hiện tại.

Ví dụ: để mô phỏng thao tác nhấn nút Màn hình chính, hãy gọi UiDevice.pressHome() .

API UI Automator

UI Automator API cho phép bạn viết các bài kiểm thử mạnh mẽ mà không cần biết về chi tiết triển khai của ứng dụng mà bạn đang nhắm mục tiêu. Bạn có thể sử dụng các API này để thu thập và thao tác với các thành phần giao diện người dùng trên nhiều ứng dụng:

  • UiObject2: Biểu thị một thành phần trên giao diện người dùng hiển thị trên thiết bị.
  • BySelector: Chỉ định tiêu chí để so khớp các phần tử trên giao diện người dùng.
  • By: Tạo BySelector một cách ngắn gọn.
  • Configurator: Cho phép bạn đặt các tham số chính để chạy kiểm thử Trình tự động hoá giao diện người dùng.

Ví dụ: mã sau đây cho biết cách bạn có thể viết một tập lệnh kiểm thử mở một ứng dụng Gmail trên thiết bị:

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

Thiết lập Trình tự động hoá giao diện người dùng

Trước khi tạo bài kiểm thử giao diện người dùng bằng UI Automator, hãy nhớ định cấu hình bài kiểm thử vị trí của mã nguồn và phần phụ thuộc của dự án, như mô tả trong bài viết Thiết lập dự án cho AndroidX Test.

Trong tệp build.gradle của mô-đun ứng dụng Android, bạn phải thiết lập phần phụ thuộc tham chiếu đến thư viện UI Automator:

Kotlin

dependencies {
  ...
  androidTestImplementation('androidx.test.uiautomator:uiautomator:2.3.0-alpha03')
}

Groovy

dependencies {
  ...
  androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.3.0-alpha03'
}

Để tối ưu hoá việc kiểm thử UI Automator của mình, trước tiên, bạn nên kiểm tra thành phần giao diện người dùng và đảm bảo rằng các thành phần đó có thể truy cập được. Những mẹo tối ưu hoá này được mô tả trong hai phần tiếp theo.

Kiểm tra giao diện người dùng trên thiết bị

Trước khi thiết kế kiểm thử, hãy kiểm tra các thành phần giao diện người dùng hiển thị trên thiết bị. Để đảm bảo rằng các bài kiểm thử Trình tự động hoá giao diện người dùng của bạn có thể truy cập vào các thành phần này, hãy kiểm tra để đảm bảo các thành phần này có nhãn văn bản hiển thị, Giá trị android:contentDescription hoặc cả hai.

Công cụ uiautomatorviewer cung cấp một giao diện trực quan thuận tiện để kiểm tra hệ phân cấp bố cục và xem thuộc tính của các thành phần giao diện người dùng có thể nhìn thấy trên nền trước của thiết bị. Thông tin này cho phép bạn tạo thêm kiểm thử chi tiết bằng UI Automator. Ví dụ: bạn có thể tạo bộ chọn giao diện người dùng khớp với một thuộc tính hiển thị cụ thể.

Cách chạy công cụ uiautomatorviewer:

  1. Chạy ứng dụng đích trên một thiết bị thực.
  2. Kết nối thiết bị với máy phát triển của bạn.
  3. Mở một cửa sổ dòng lệnh rồi chuyển đến thư mục <android-sdk>/tools/.
  4. Chạy công cụ này bằng lệnh sau:
 $ uiautomatorviewer

Cách xem các thuộc tính giao diện người dùng cho ứng dụng:

  1. Trong giao diện uiautomatorviewer, hãy nhấp vào nút Device Capture (Ảnh chụp màn hình thiết bị).
  2. Di chuột qua ảnh chụp nhanh trong bảng điều khiển bên trái để xem các thành phần giao diện người dùng do công cụ uiautomatorviewer xác định. Cơ sở lưu trú được liệt kê trong thấp hơn bảng điều khiển bên phải và hệ phân cấp bố cục trong bảng điều khiển phía trên bên phải.
  3. (Không bắt buộc) Nhấp vào nút Bật/tắt nút NAF để xem các thành phần giao diện người dùng mà UI Automator không thể truy cập. Có thể chỉ có một số ít thông tin có sẵn cho các thành phần này.

Để tìm hiểu về các loại thành phần giao diện người dùng phổ biến do Android cung cấp, hãy xem bài viết Người dùng Giao diện.

Đảm bảo hoạt động của bạn có thể truy cập được

Khung kiểm thử UI Automator hoạt động tốt hơn trên các ứng dụng đã triển khai Bộ tính năng hỗ trợ tiếp cận của Android. Khi bạn sử dụng các thành phần trên giao diện người dùng thuộc loại View, hoặc một lớp con của View từ SDK, thì bạn không cần triển khai chức năng hỗ trợ tiếp cận vì các lớp này đã làm việc đó cho bạn.

Tuy nhiên, một số ứng dụng sử dụng các phần tử tuỳ chỉnh trên giao diện người dùng để cung cấp trải nghiệm người dùng phong phú hơn. Các phần tử như vậy sẽ không cung cấp tính năng tự động hỗ trợ tiếp cận. Nếu ứng dụng của bạn chứa các thực thể của một lớp con của View không phải từ SDK, hãy tạo bạn cần thêm bộ tính năng hỗ trợ tiếp cận vào các phần tử này bằng cách hoàn tất các bước sau:

  1. Tạo một lớp cụ thể mở rộng ExploreByTouchHelper.
  2. Liên kết một bản sao của lớp mới với một phần tử giao diện người dùng tuỳ chỉnh cụ thể bằng cách đang gọi setAccessibilityDelegate().

Để được hướng dẫn thêm về cách thêm bộ tính năng hỗ trợ tiếp cận vào khung hiển thị tuỳ chỉnh , xem Chế độ xem tuỳ chỉnh có thể hỗ trợ tiếp cận cho toà nhà. Để tìm hiểu thêm về các phương pháp chung hay nhất về khả năng hỗ trợ tiếp cận trên Android, hãy xem Giúp ứng dụng trở nên đa dạng hơn Có hỗ trợ tiếp cận.

Tạo lớp kiểm thử Automator cho giao diện người dùng

Lớp kiểm thử UI Automator của bạn phải được viết giống như bài kiểm thử JUnit 4 . Để tìm hiểu thêm về cách tạo các lớp kiểm thử JUnit 4 và sử dụng JUnit 4 câu nhận định và chú giải, hãy xem Tạo lớp kiểm thử đơn vị được đo lường.

Thêm chú thích @RunWith(AndroidJUnit4.class) ở đầu bài kiểm thử định nghĩa lớp. Bạn cũng cần chỉ định lớp AndroidJUnitRunner, được cung cấp trong AndroidX Test, làm trình chạy kiểm thử mặc định. Bước này được mô tả chi tiết hơn trong bài viết Chạy kiểm thử Trình tự động hoá giao diện người dùng trên một thiết bị hoặc trình mô phỏng.

Triển khai mô hình lập trình sau đây trong lớp kiểm thử Automator của giao diện người dùng:

  1. Lấy đối tượng UiDevice để truy cập vào thiết bị bạn muốn kiểm thử bằng cách gọi phương thức getInstance() và truyền vào phương thức đó một đối tượng Instrumentation dưới dạng đối số.
  2. Lấy đối tượng UiObject2 để truy cập vào thành phần giao diện người dùng hiện trên thiết bị (ví dụ: khung hiển thị hiện tại trong nền trước), bằng cách gọi phương thức findObject().
  3. Mô phỏng một hoạt động tương tác cụ thể của người dùng để thực hiện trên thành phần giao diện người dùng đó, bằng cách gọi một phương thức UiObject2; ví dụ: gọi scrollAllowed() để cuộn và setText() để chỉnh sửa trường văn bản. Bạn có thể gọi API ở bước 2 và 3 lặp lại nhiều lần khi cần thiết để thử nghiệm các tương tác phức tạp hơn của người dùng liên quan đến nhiều thành phần giao diện người dùng hoặc trình tự hành động của người dùng.
  4. Kiểm tra để đảm bảo giao diện người dùng phản ánh trạng thái hoặc hành vi dự kiến sau khi người dùng này các hoạt động tương tác được thực hiện.

Các bước này sẽ được đề cập chi tiết hơn ở các phần bên dưới.

Truy cập vào các thành phần giao diện người dùng

Đối tượng UiDevice là cách chính để bạn truy cập và thao tác trạng thái của thiết bị. Trong các chương trình kiểm thử của mình, bạn có thể gọi các phương thức UiDevice để kiểm tra trạng thái của các thuộc tính, chẳng hạn như hướng hoặc kích thước màn hình hiện tại. Kiểm thử của bạn có thể sử dụng đối tượng UiDevice để thực hiện các thao tác ở cấp thiết bị, chẳng hạn như buộc thiết bị vào một chế độ xoay cụ thể, nhấn phần cứng D-pad và nhấn nút Màn hình chính và nút Trình đơn.

Bạn nên bắt đầu kiểm thử từ Màn hình chính của thiết bị. Từ màn hình chính (hoặc một số vị trí bắt đầu khác mà bạn đã chọn trong thiết bị), bạn có thể gọi các phương thức do UI Automator API cung cấp để chọn và tương tác với các thành phần cụ thể trên giao diện người dùng.

Đoạn mã sau đây cho thấy cách thử nghiệm của bạn có thể nhận được một thực thể của UiDevice và mô phỏng thao tác nhấn nút Màn hình chính:

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

Trong ví dụ này, câu lệnh @SdkSuppress(minSdkVersion = 18) giúp đảm bảo rằng bài kiểm thử sẽ chỉ chạy trên thiết bị Android 4.3 (API cấp 18) trở lên, theo yêu cầu của khung UI Automator.

Sử dụng phương thức findObject() để truy xuất UiObject2 biểu thị một khung hiển thị khớp với một tiêu chí cụ thể của bộ chọn. Bạn có thể sử dụng lại UiObject2 các bản sao bạn đã tạo trong các phần khác của quá trình kiểm thử ứng dụng nếu cần. Lưu ý rằng khung kiểm thử UI Automator sẽ tìm kiếm màn hình hiện tại cho khớp mỗi khi kiểm thử của bạn sử dụng thực thể UiObject2 để nhấp vào một giao diện người dùng hoặc truy vấn một thuộc tính.

Đoạn mã sau đây cho thấy cách kiểm thử của bạn có thể tạo UiObject2 thực thể đại diện cho nút Cancel (Huỷ) và nút OK trong ứng dụng.

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

Chỉ định bộ chọn

Nếu bạn muốn truy cập vào một thành phần giao diện người dùng cụ thể trong một ứng dụng, hãy sử dụng Lớp By để tạo một thực thể BySelector. BySelector biểu thị một truy vấn cho các phần tử cụ thể trong giao diện người dùng được hiển thị.

Nếu có nhiều phần tử phù hợp được tìm thấy thì phần tử phù hợp đầu tiên trong hệ phân cấp bố cục được trả về dưới dạng UiObject2 mục tiêu. Khi xây dựng một BySelector, bạn có thể liên kết nhiều thuộc tính với nhau để tinh chỉnh tìm kiếm. Nếu không tìm thấy thành phần giao diện người dùng phù hợp, hàm sẽ trả về null.

Bạn có thể sử dụng phương thức hasChild() hoặc hasDescendant() để lồng nhiều thực thể BySelector. Ví dụ: đoạn mã ví dụ sau đây cho thấy cách kiểm thử của bạn có thể chỉ định một lượt tìm kiếm để tìm ListView đầu tiên có một phần tử con trên giao diện người dùng với thuộc tính văn bản.

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")
        )
);

Việc chỉ định trạng thái đối tượng trong tiêu chí của bộ chọn có thể hữu ích. Cho ví dụ: nếu bạn muốn chọn một danh sách tất cả các phần tử đã đánh dấu để bạn có thể bỏ đánh dấu các tuỳ chọn đó, hãy gọi phương thức checked() với đối số được đặt thành true.

Thực hiện các thao tác

Sau khi chương trình kiểm thử nhận được đối tượng UiObject2, bạn có thể gọi các phương thức trong lớp UiObject2 để thực hiện các tương tác của người dùng trên thành phần giao diện người dùng được đại diện bởi đối tượng đó. Bạn có thể chỉ định các thao tác như:

  • click() : Nhấp vào phần giữa các ranh giới hiển thị của thành phần trên giao diện người dùng.
  • drag() : Kéo đối tượng này đến các toạ độ tuỳ ý.
  • setText() : Đặt văn bản trong trường có thể chỉnh sửa sau khi xoá nội dung của trường. Ngược lại, phương thức clear() sẽ xoá văn bản hiện có trong trường có thể chỉnh sửa.
  • swipe() : Thực hiện thao tác vuốt theo hướng đã chỉ định.
  • scrollUntil(): Thực hiện thao tác cuộn theo hướng đã chỉ định cho đến khi Condition hoặc EventCondition được đáp ứng.

Khung kiểm thử UI Automator cho phép bạn gửi một Ý định hoặc khởi chạy một Hoạt động mà không cần sử dụng các lệnh shell, bằng cách lấy Ngữ cảnh đối tượng thông qua getContext().

Đoạn mã sau đây cho biết cách kiểm thử của bạn có thể sử dụng một Ý định để khởi chạy ứng dụng đang được kiểm thử. Phương pháp này hữu ích khi bạn chỉ muốn thử nghiệm ứng dụng máy tính và không quan tâm đến trình chạy.

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

Xác minh kết quả

ToolsationTestCase mở rộng TestCase để bạn có thể sử dụng phương thức Xác nhận tiêu chuẩn của JUnit để kiểm thử các thành phần giao diện người dùng đó trong ứng dụng trả về các kết quả mong đợi.

Đoạn mã sau đây cho thấy cách thử nghiệm của bạn có thể xác định vị trí một số nút trong một ứng dụng tính toán, nhấp vào chúng theo thứ tự, sau đó xác minh rằng kết quả chính xác là được hiển thị.

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

Chạy chương trình kiểm thử UI Automator trên một thiết bị hoặc trình mô phỏng

Bạn có thể chạy kiểm thử UI Automator từ Android Studio hoặc từ dòng lệnh. Hãy nhớ chỉ định AndroidJUnitRunner làm giá trị mặc định trình chạy đo lường trong dự án của bạn.

Ví dụ khác

Tương tác với giao diện người dùng hệ thống

UI Automator có thể tương tác với mọi nội dung trên màn hình, bao gồm cả hệ thống bên ngoài ứng dụng, như thể hiện trong các đoạn mã sau:

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

Chờ chuyển đổi

Tắt chế độ làm phiền
Hình 1. UI Automator tắt chế độ Không làm phiền trên thiết bị thử nghiệm.

Việc chuyển đổi màn hình có thể tốn thời gian và việc dự đoán thời lượng của quá trình chuyển đổi này không đáng tin cậy, vì vậy bạn nên thiết lập UI Automator để chờ sau khi thực hiện thao tác. Trình tự động hoá giao diện người dùng cung cấp nhiều phương thức để thực hiện việc này:

Đoạn mã sau đây cho biết cách sử dụng UI Automator để tắt chế độ Không nên Chế độ làm phiền trong phần Cài đặt hệ thống bằng phương thức performActionAndWait() chờ chuyển đổi:

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

Tài nguyên khác

Để biết thêm thông tin về cách sử dụng UI Automator trong kiểm thử Android, hãy tham khảo các tài nguyên sau đây.

Tài liệu tham khảo:

Mẫu

  • BasicSample: Mẫu Automator giao diện người dùng cơ bản.