UI Automator là một khung kiểm thử giao diện người dùng phù hợp để kiểm thử chức năng trên giao diện người dùng trên nhiều ứng dụng trên hệ thống và các ứng dụng đã cài đặt. API UI Automator cho phép bạn tương tác với các phần tử hiển thị trên thiết bị, bất kể Activity
nào đang được lấy làm tâm điểm, nhờ đó, bạn có thể 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ị kiểm thử. Chương 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 các phần mô tả tiện lợi, chẳng hạn như văn bản xuất hiện trong thành phần đó hoặc phần mô tả nội dung của thành phần đó.
Khung kiểm thử UI Automator là một API dựa trên khả năng đo lường và hoạt động với 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 thông tin triển khai nội bộ của ứng dụng mục tiêu.
Các tính năng chính của khung kiểm thử giao diện người dùng Automator bao gồm:
- Một API để truy xuất thông tin trạng thái và thực hiện các thao tác trên thiết bị mục tiêu. Để biết thêm thông tin, hãy xem bài viết Truy cập vào trạng thái thiết bị.
- Các API hỗ trợ kiểm thử giao diện người dùng trên nhiều ứng dụng. Để biết thêm thông tin, hãy xem phần API UI Automator.
Truy cập vào trạng thái thiết bị
Khung kiểm thử giao diện người dùng 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 mục tiêu đang chạy. Bạn có thể gọi các phương thức để truy cập vào các thuộc tính của thiết bị, chẳng hạn như hướng hoặc kích thước hiển thị hiện tại. Lớp UiDevice
cũng cho phép bạn thực hiện các thao tác sau:
- Thay đổi hướng xoay thiết bị.
- Nhấn phím phần cứng, chẳng hạn như "tăng âm lượng".
- Nhấn nút Quay lại, Màn hình chính hoặc Trình đơn.
- Mở ngăn thông báo.
- 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 phương thức UiDevice.pressHome()
.
API UI Automator
API Automator của giao diện người dùng cho phép bạn viết các kiểm thử mạnh mẽ mà không cần biết 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 để ghi lại 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
: Đại diện cho 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í để khớp với các thành phần trên giao diện người dùng.By
: TạoBySelector
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ử Automator trên giao diện người dùng.
Ví dụ: Mã sau đây cho biết cách bạn có thể viết tập lệnh kiểm thử để mở một ứng dụng Gmail trong 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 UI Automator
Trước khi tạo kiểm thử giao diện người dùng bằng UI Automator, hãy nhớ định cấu hình vị trí mã nguồn kiểm thử và các 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 đặt tham chiếu phần phụ thuộc đến thư viện Automator trên giao diện người dùng:
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ử Automator trên giao diện người dùng, trước tiên, bạn nên kiểm tra các thành phần trên giao diện người dùng của ứng dụng mục tiêu 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 2 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 các bài kiểm thử Automator trên 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 để chắc chắn rằng 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ệ thống phân cấp bố cục và xem những thuộc tính của các thành phần trên giao diện người dùng có thể quan sát được 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 nhiều chương trình kiểm thử chi tiết bằng cách sử dụ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
:
- Chạy ứng dụng đích trên một thiết bị thực.
- Kết nối thiết bị với máy phát triển.
- Mở cửa sổ dòng lệnh rồi chuyển đến thư mục
<android-sdk>/tools/
. - Chạy công cụ 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:
- Trong giao diện
uiautomatorviewer
, hãy nhấp vào nút Ảnh chụp màn hình thiết bị. - 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 mà công cụ
uiautomatorviewer
xác định. Các thuộc tính được liệt kê trong bảng điều khiển phía dưới bên phải và hệ phân cấp bố cục trong bảng điều khiển trên bên phải. - Bạn có thể nhấp vào nút Toggle NAF Nodes (Bật/tắt nút NAF) để xem các thành phần giao diện người dùng mà Automator giao diện người dùng không thể truy cập được. Có thể chỉ có một số ít thông tin được cung cấp 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 Giao diện người dùng.
Đảm bảo Google có thể truy cập vào hoạt động của bạn
Khung kiểm thử giao diện người dùng 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 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, bạn không cần triển khai tính năng hỗ trợ tiếp cận, vì các lớp này đã thực hiện việc đó cho bạn.
Tuy nhiên, một số ứng dụng sử dụng thành phần tuỳ chỉnh trên giao diện người dùng để mang lại 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 hỗ trợ tiếp cận tự động. Nếu ứng dụng của bạn chứa các thực thể của một lớp con View
không phải từ SDK, hãy nhớ 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 thành các bước sau:
- Tạo một lớp cụ thể giúp mở rộng ExploreByTouchHelper.
- Liên kết một thực thể 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 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 các phần tử của thành phần hiển thị tuỳ chỉnh, vui lòng xem bài viết Tạo thành phần hiển thị tuỳ chỉnh có thể truy cập được. Để tìm hiểu thêm về các phương pháp chung hay nhất về hỗ trợ tiếp cận trên Android, hãy xem bài viết Làm cho ứng dụng dễ tiếp cận hơn.
Tạo lớp kiểm thử giao diện người dùng Automator
Bạn nên viết lớp kiểm thử giao diện người dùng Automator giống như lớp kiểm thử JUnit 4. Để tìm hiểu thêm về cách tạo lớp kiểm thử JUnit 4, cũng như sử dụng câu nhận định và chú giải JUnit 4, hãy xem phần Tạo lớp kiểm thử đơn vị được đo lường.
Thêm chú thích @RunWith(AndroidJUnit4.class) ở đầu phần định nghĩa lớp kiểm thử. 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ử Automator trên 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 trong lớp kiểm thử Automator trên giao diện người dùng:
- 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 đối tượng Instrumentation làm đối số. - Lấy đối tượng
UiObject2
để truy cập vào một thành phần giao diện người dùng hiển thị trên thiết bị (ví dụ: khung hiển thị hiện tại ở nền trước), bằng cách gọi phương thức findObject(). - 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 scroll nơi() để cuộn và setText() để chỉnh sửa trường văn bản. Bạn có thể gọi các API ở bước 2 và 3 nhiều lần nếu cần để kiểm thử các hoạt động tương tác phức tạp hơn của người dùng có liên quan đến nhiều thành phần giao diện người dùng hoặc trình tự thao tác của người dùng. - 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 thực hiện các hoạt động tương tác của người dùng này.
Các bước này được đề cập chi tiết hơn trong các phần dưới đây.
Truy cập 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 với trạng thái của thiết bị. Trong kiểm thử, 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ó 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ị xoay theo một chế độ xoay cụ thể, nhấn các nút phần cứng D-pad rồi nhấn nút Màn hình chính và 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ị. Trên Màn hình chính (hoặc một số vị trí xuất phát khác mà bạn đã chọn trong thiết bị), bạn có thể gọi các phương thức do API Automator của giao diện người dùng cung cấp để chọn và tương tác với các phần tử trên giao diện người dùng cụ thể.
Đoạn mã sau đây cho thấy cách bài kiểm thử của bạn có thể nhận một thực thể của UiDevice
và mô phỏng một 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ụ, câu lệnh @SdkSuppress(minSdkVersion = 18) giúp đảm bảo rằng các hoạt động kiểm thử sẽ chỉ chạy trên những thiết bị có 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
, đại diện cho
thành phần hiển thị khớp với một tiêu chí nhất định của bộ chọn. Bạn có thể sử dụng lại các thực thể UiObject2
mà 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ử Automator trên giao diện người dùng sẽ tìm kiếm kết quả trùng khớp trên màn hình hiện tại mỗi khi kiểm thử sử dụng thực thể UiObject2
để nhấp vào một phần tử trên 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 bài kiểm thử của bạn có thể tạo các thực thể UiObject2
biểu thị 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 ứng dụng, hãy dùng lớp By
để tạo thực thể BySelector
. BySelector
đại diện cho truy vấn đối với các phần tử cụ thể trong giao diện người dùng được hiển thị.
Nếu tìm thấy nhiều phần tử phù hợp, thì phần tử phù hợp đầu tiên trong hệ phân cấp bố cục sẽ được trả về dưới dạng UiObject2
mục tiêu. Khi tạo BySelector
, bạn có thể liên kết nhiều thuộc tính lại với nhau để tinh chỉnh nội dung tìm kiếm của mình. Nếu không tìm thấy thành phần trên giao diện người dùng phù hợp, thì null
sẽ được trả về.
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ụ: mã ví dụ sau cho thấy cách kiểm thử của bạn có thể chỉ định một cụm từ tìm kiếm để tìm ListView
đầu tiên có thành phần giao diện người dùng con 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") ) );
Bạn nên chỉ định trạng thái đối tượng trong tiêu chí bộ chọn. Ví dụ: nếu bạn muốn chọn danh sách tất cả phần tử đã đánh dấu để có thể bỏ đánh dấu các phần tử đó, 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 kiểm thử đã có đượ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 hoạt động tương tác của người dùng trên thành phần giao diện người dùng do đối tượng đó biểu thị. Bạn có thể chỉ định các hành động đó như sau:
click()
: Nhấp vào giữa 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 toạ độ tuỳ ý.setText()
: Đặt văn bản trong một 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ứcclear()
sẽ xoá văn bản hiện có trong một 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 khiCondition
hoặcEventCondition
được đáp ứng.
Khung kiểm thử giao diện người dùng Automator cho phép bạn gửi một Ý định hoặc 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 đối tượng Ngữ cảnh thông qua getContext()
.
Đoạn mã sau đây cho biết cách chương trình kiểm thử của bạn có thể sử dụng Ý định để 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 kiểm thử ứng dụng tính toán 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ả
InstrumentationTestCase mở rộng TestCase, vì vậy, bạn có thể sử dụng các phương thức Assert JUnit tiêu chuẩn để kiểm thử các thành phần giao diện người dùng trong ứng dụng trả về kết quả dự kiến.
Đoạn mã sau đây cho biết cách bài kiểm thử của bạn có thể xác định vị trí một số nút trong ứng dụng tính toán, nhấp vào các nút theo thứ tự rồi xác minh rằng kết quả hiển thị đúng.
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 kiểm thử giao diện người dùng Automator trên một thiết bị hoặc trình mô phỏng
Bạn có thể chạy kiểm thử giao diện người dùng Automator qua Android Studio hoặc qua dòng lệnh. Hãy nhớ chỉ định AndroidJUnitRunner
làm trình chạy đo lường mặc định 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 thứ trên màn hình, bao gồm cả các phần tử hệ thống bên ngoài ứng dụng, như 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ờ hiệu ứng chuyển đổi
![Tắt tính năng làm phiền](https://developer.android.com/static/images/testing/uiautomator_turn_off_disturb.gif?authuser=6&hl=vi)
Quá trình chuyển đổi màn hình có thể mất thời gian và dự đoán thời lượng của các hiệu ứng chuyển đổi này không đáng tin cậy. Vì vậy, bạn nên yêu cầu UI Automator đợi sau khi thực hiện các thao tác. UI Automator cung cấp nhiều phương thức để thực hiện việc này:
UiDevice.performActionAndWait(Runnable action, EventCondition<U> condition, long timeout)
: Ví dụ như để nhấp vào một nút và đợi cho đến khi một cửa sổ mới xuất hiện, hãy gọidevice.performActionAndWait(() -> button.click(), Until.newWindow(), timeout)
UiDevice.wait(Condition<Object, U> condition, long timeout)
: Ví dụ: để đợi cho đến khi có mộtUiObject2
nhất định trên thiết bị, hãy gọidevice.wait(device.hasObject(By.text("my_text")), timeout);
UiObject2.wait(@NonNull Condition<Object, U> condition, long timeout)
: Ví dụ: để đợi cho đến khi một hộp đánh dấu được đánh dấu, hãy gọicheckbox.wait(Until.checked(true), timeout);
UiObject2.clickAndWait(@NonNull EventCondition<U> condition, long timeout)
: Ví dụ như khi nhấp vào một nút rồi đợi cho đến khi một cửa sổ mới xuất hiện, hãy gọibutton.clickAndWait(Until.newWindow(), timeout);
UiObject2.scrollUntil(@NonNull Direction direction, @NonNull Condition<Object, U> condition)
: Ví dụ như để cuộn xuống cho đến khi một đối tượng mới xuất hiện, hãy gọiobject.scrollUntil(Direction.DOWN, Until.hasObject(By.text('new_obj')));
UiObject2.scrollUntil(@NonNull Direction direction, @NonNull EventCondition<U> condition)
: Ví dụ như để cuộn xuống dưới cùng, hãy gọiobject.scrollUntil(Direction.DOWN, Until.scrollFinished(Direction.DOWN));
Đoạn mã sau đây cho biết cách sử dụng UI Automator để tắt chế độ Không làm phiền trong phần Cài đặt hệ thống bằng phương thức performActionAndWait()
đang 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.
Tài liệu tham khảo:
Mẫu
- BasicSample: Mẫu Automator của giao diện người dùng cơ bản.