UI Automator הוא framework לבדיקת ממשק משתמש שמתאים לבדיקות פונקציונליות של ממשק משתמש באפליקציות שונות, במערכת ובאפליקציות מותקנות. ממשקי ה-API של UI Automator מאפשרים אינטראקציה עם רכיבים גלויים במכשיר, בלי קשר לActivity
שנמצא בפוקוס, כך שאפשר לבצע פעולות כמו פתיחת תפריט ההגדרות או מרכז האפליקציות במכשיר בדיקה. בבדיקה אפשר לחפש רכיב בממשק המשתמש באמצעות תיאורים נוחים כמו הטקסט שמוצג ברכיב או תיאור התוכן שלו.
UI Automator הוא API מבוסס-אינסטרומנטציה שפועל עם רץ הבדיקות AndroidJUnitRunner
. הוא מתאים במיוחד לכתיבת בדיקות אוטומטיות בסגנון קופסה אטומה, שבהן קוד הבדיקה לא מסתמך על פרטי הטמעה פנימיים של אפליקציית היעד.
התכונות העיקריות של מסגרת הבדיקה UI Automator כוללות את התכונות הבאות:
- ממשק API לאחזור מידע על מצב המכשיר ולביצוע פעולות במכשיר היעד. מידע נוסף זמין במאמר בנושא גישה למצב המכשיר.
- ממשקי API שתומכים בבדיקות של ממשקי משתמש באפליקציות שונות. מידע נוסף זמין במאמר ממשקי API של UI Automator.
גישה למצב המכשיר
Framework הבדיקה UI Automator מספק מחלקה UiDevice
לגישה למכשיר שבו פועלת אפליקציית היעד ולביצוע פעולות בו. אפשר להתקשר לשיטות שלו כדי לגשת למאפייני המכשיר, כמו האוריינטציה הנוכחית או גודל המסך. בנוסף, המחלקה UiDevice
מאפשרת לבצע את הפעולות הבאות:
- שינוי כיוון הסיבוב של המכשיר.
- לוחצים על מקשי חומרה, כמו 'הגברת עוצמת הקול'.
- לוחצים על הלחצנים 'חזרה', 'בית' או 'תפריט'.
- פותחים את לוח ההתראות.
- מצלמים את המסך של החלון הנוכחי.
לדוגמה, כדי לדמות לחיצה על הלחצן הראשי, קוראים לשיטה UiDevice.pressHome()
.
UI Automator APIs
ממשקי ה-API של UI Automator מאפשרים לכם לכתוב בדיקות חזקות בלי שתצטרכו לדעת פרטים על ההטמעה של האפליקציה שאתם מכוונים אליה. אפשר להשתמש בממשקי ה-API האלה כדי לצלם ולערוך רכיבי ממשק משתמש בכמה אפליקציות:
-
UiObject2
: מייצג רכיב בממשק המשתמש שמוצג במכשיר. -
BySelector
: מציין קריטריונים להתאמה של רכיבים בממשק המשתמש. -
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, צריך להגדיר הפניה לתלות בספריית UI Automator:
Kotlin
dependencies {
...
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
}
גרוב
dependencies {
...
androidTestImplementation "androidx.test.uiautomator:uiautomator:2.3.0"
}
כדי לבצע אופטימיזציה של הבדיקות באמצעות UI Automator, קודם צריך לבדוק את רכיבי ממשק המשתמש של אפליקציית היעד ולוודא שיש אליהם גישה. הטיפים האלה לאופטימיזציה מפורטים בשני הקטעים הבאים.
בדיקת ממשק המשתמש במכשיר
לפני שתתכננו את הבדיקה, כדאי לבדוק את רכיבי ממשק המשתמש שגלויים במכשיר. כדי לוודא שבדיקות UI Automator יכולות לגשת לרכיבים האלה, צריך לבדוק אם לרכיבים האלה יש תוויות טקסט גלויות, ערכי android:contentDescription
או שניהם.
uiautomatorviewer
הכלי מספק ממשק חזותי נוח לבדיקת ההיררכיה של הפריסה ולצפייה במאפיינים של רכיבים בממשק המשתמש שגלויים בחזית המכשיר. המידע הזה מאפשר לכם ליצור בדיקות מפורטות יותר באמצעות UI Automator. לדוגמה, אפשר ליצור בורר של ממשק משתמש שתואם למאפיין ספציפי שגלוי למשתמש.
כדי להפעיל את הכלי uiautomatorviewer
:
- מפעילים את אפליקציית היעד במכשיר פיזי.
- מחברים את המכשיר למחשב הפיתוח.
- פותחים חלון טרמינל ועוברים לספרייה
<android-sdk>/tools/
. - מריצים את הכלי באמצעות הפקודה הבאה:
$ uiautomatorviewer
כדי לראות את מאפייני ממשק המשתמש של האפליקציה:
- בממשק
uiautomatorviewer
, לוחצים על הלחצן צילום מסך של המכשיר. - מעבירים את העכבר מעל התמונה בחלונית הימנית כדי לראות את רכיבי ממשק המשתמש שזוהו על ידי הכלי
uiautomatorviewer
. הנכסים מופיעים בחלונית השמאלית התחתונה, והיררכיית הפריסה מופיעה בחלונית השמאלית העליונה. - אפשר גם ללחוץ על הלחצן Toggle NAF Nodes כדי לראות רכיבי ממשק משתמש שלא נגישים ל-UI Automator. יכול להיות שיהיה מידע מוגבל בלבד לגבי הרכיבים האלה.
מידע על הסוגים הנפוצים של רכיבי ממשק משתמש ש-Android מספקת זמין במאמר ממשק משתמש.
מוודאים שאפשר לגשת לפעילות
מסגרת הבדיקה UI Automator פועלת טוב יותר באפליקציות שבהן הוטמעו תכונות הנגישות של Android. כשמשתמשים באלמנטים של ממשק משתמש מהסוג View
, או במחלקה משנית של View
מה-SDK, לא צריך להטמיע תמיכה בנגישות, כי המחלקות האלה כבר עושות את זה בשבילכם.
עם זאת, אפליקציות מסוימות משתמשות ברכיבי ממשק משתמש מותאמים אישית כדי לספק חוויית משתמש עשירה יותר.
רכיבים כאלה לא יספקו תמיכה אוטומטית בנגישות. אם האפליקציה שלכם מכילה מקרים של מחלקת משנה של View
שלא מגיעה מ-SDK, חשוב להוסיף רכיבי נגישות לאלמנטים האלה. לשם כך, צריך לבצע את השלבים הבאים:
- יוצרים מחלקה קונקרטית שמרחיבה את ExploreByTouchHelper.
- כדי לשייך מופע של המחלקה החדשה לרכיב ספציפי בממשק המשתמש בהתאמה אישית, צריך לקרוא ל-setAccessibilityDelegate().
הנחיות נוספות להוספת תכונות נגישות לרכיבי תצוגה בהתאמה אישית זמינות במאמר יצירת תצוגות בהתאמה אישית עם נגישות. כדי לקבל מידע נוסף על שיטות מומלצות כלליות לנגישות ב-Android, אפשר לעיין במאמר בנושא הנגשת אפליקציות.
יצירת מחלקת בדיקה של UI Automator
מחלקת הבדיקה של UI Automator צריכה להיכתב באותו אופן כמו מחלקת בדיקה של JUnit 4. מידע נוסף על יצירת מחלקות בדיקה של JUnit 4 ועל שימוש בהצהרות ובאנוטציות של JUnit 4 זמין במאמר יצירת מחלקת בדיקה של יחידה עם מכשור.
מוסיפים את ההערה @RunWith(AndroidJUnit4.class) בתחילת ההגדרה של מחלקת הבדיקה. צריך גם לציין את המחלקה AndroidJUnitRunner, שמסופקת ב-AndroidX Test, ככלי ברירת המחדל להרצת בדיקות. השלב הזה מתואר בפירוט נוסף במאמר הרצת בדיקות UI Automator במכשיר או באמולטור.
מטמיעים את מודל התכנות הבא במחלקת הבדיקה של UI Automator:
- כדי לקבל אובייקט
UiDevice
כדי לגשת למכשיר שרוצים לבדוק, קוראים למתודה getInstance() ומעבירים לה אובייקט Instrumentation כארגומנט. - כדי לקבל אובייקט
UiObject2
ולגשת לרכיב בממשק המשתמש שמוצג במכשיר (לדוגמה, התצוגה הנוכחית בחזית), צריך לבצע קריאה לשיטה findObject(). - מדמים אינטראקציה ספציפית של משתמש עם רכיב ממשק המשתמש באמצעות קריאה לשיטה
UiObject2
. לדוגמה, קוראים ל-scrollUntil() כדי לגלול, ול-setText() כדי לערוך שדה טקסט. אפשר להפעיל את ממשקי ה-API בשלבים 2 ו-3 שוב ושוב לפי הצורך כדי לבדוק אינטראקציות מורכבות יותר של משתמשים שכוללות רכיבים מרובים של ממשק המשתמש או רצפים של פעולות משתמש. - בודקים שממשק המשתמש משקף את המצב או את אופן הפעולה הצפויים, אחרי ביצוע האינטראקציות האלה של המשתמש.
השלבים האלה מוסברים בפירוט בקטעים הבאים.
גישה לרכיבי ממשק המשתמש
אובייקט UiDevice
הוא הדרך העיקרית לגשת למצב המכשיר ולשנות אותו. בבדיקות, אפשר להפעיל שיטות של UiDevice
כדי לבדוק את המצב של מאפיינים שונים, כמו האוריינטציה הנוכחית או גודל המסך.
אפשר להשתמש באובייקט UiDevice
בבדיקה כדי לבצע פעולות ברמת המכשיר, כמו כניסה בכוח לסיבוב ספציפי, לחיצה על לחצני חומרה של D-pad ולחיצה על הלחצנים Home ו-Menu.
מומלץ להתחיל את הבדיקה ממסך הבית של המכשיר. ממסך הבית (או ממיקום התחלתי אחר שבחרתם במכשיר), אתם יכולים לקרוא לשיטות שסופקו על ידי UI Automator API כדי לבחור אינטראקציה עם רכיבי ממשק משתמש ספציפיים.
בקטע הקוד הבא מוצג איך הבדיקה יכולה לקבל מופע של
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 test framework מחפש התאמה בתצוגה הנוכחית בכל פעם שהבדיקה משתמשת במופע UiObject2
כדי ללחוץ על רכיב בממשק המשתמש או כדי לשלוח שאילתה לגבי מאפיין.
בקטע הקוד הבא מוצג אופן ההגדרה של 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();
}
ציון בורר
אם רוצים לגשת לרכיב ספציפי בממשק המשתמש באפליקציה, צריך להשתמש במחלקה By
כדי ליצור מופע של BySelector
. BySelector
מייצג שאילתה לרכיבים ספציפיים בממשק המשתמש שמוצג.
אם נמצא יותר מרכיב אחד שתואם, מוחזר הרכיב התואם הראשון בהיררכיית הפריסה כיעד UiObject2
. כשיוצרים BySelector
, אפשר לשרשר כמה מאפיינים כדי לדייק את החיפוש. אם לא נמצא רכיב תואם בממשק המשתמש, מוחזר null
.
אפשר להשתמש ב-method hasChild()
או ב-method 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()
עם הארגומנט שמוגדר כ-true.
ביצוע פעולות
אחרי שהבדיקה מקבלת אובייקט UiObject2
, אפשר לקרוא למתודות במחלקה UiObject2
כדי לבצע אינטראקציות של משתמשים ברכיב ממשק המשתמש שמיוצג על ידי האובייקט הזה. אפשר לציין פעולות כמו:
-
click()
: לוחץ על מרכז הגבולות הגלויים של רכיב ממשק המשתמש. -
drag()
: גוררים את האובייקט הזה לקואורדינטות שרירותיות. -
setText()
: מגדיר את הטקסט בשדה שניתן לערוך, אחרי שמנקים את התוכן של השדה. לעומת זאת, השיטהclear()
מוחקת את הטקסט הקיים בשדה שניתן לעריכה. -
swipe()
: מבצע את פעולת ההחלקה לכיוון שצוין. -
scrollUntil()
: מבצע את פעולת הגלילה לכיוון שצוין עד שמתקיים התנאיCondition
אוEventCondition
.
מסגרת הבדיקה UI Automator מאפשרת לשלוח Intent או להפעיל Activity בלי להשתמש בפקודות של מעטפת, על ידי קבלת אובייקט Context דרך getContext()
.
קטע הקוד הבא מראה איך אפשר להשתמש בIntent בבדיקה כדי להפעיל את האפליקציה שנבדקת. הגישה הזו שימושית כשרוצים לבדוק רק את אפליקציית המחשבון, ולא את מרכז האפליקציות.
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, כך שאפשר להשתמש ב-methods הרגילות של Assert ב-JUnit כדי לבדוק שרכיבי ממשק המשתמש באפליקציה מחזירים את התוצאות הצפויות.
בקטע הקוד הבא מוצג אופן הפעולה של הבדיקה: איתור של כמה לחצנים באפליקציית מחשבון, לחיצה עליהם לפי הסדר ואימות התוצאה הנכונה שמוצגת.
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 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());
המתנה למעברים

מעברי מסך יכולים לקחת זמן, ואי אפשר לחזות את משך הזמן שלהם בצורה מהימנה, ולכן כדאי להשתמש ב-UI Automator כדי להמתין אחרי ביצוע פעולות. UI Automator מספק כמה שיטות לכך:
-
UiDevice.performActionAndWait(Runnable action, EventCondition<U> condition, long timeout)
: לדוגמה, כדי ללחוץ על לחצן ולהמתין עד שיופיע חלון חדש, קוראים ל-device.performActionAndWait(() -> button.click(), Until.newWindow(), timeout)
-
UiDevice.wait(Condition<Object, U> condition, long timeout)
: לדוגמה, כדי להמתין עד שיהיהUiObject2
מסוים במכשיר, קוראים ל-device.wait(Until.hasObject(By.text("my_text")), timeout);
-
UiObject2.wait(@NonNull Condition<Object, U> condition, long timeout)
: לדוגמה, כדי להמתין עד שתיבת סימון תסומן, קוראים ל-checkbox.wait(Until.checked(true), timeout);
-
UiObject2.clickAndWait(@NonNull EventCondition<U> condition, long timeout)
: לדוגמה, כדי ללחוץ על לחצן ולהמתין עד שיופיע חלון חדש, קוראים לפונקציהbutton.clickAndWait(Until.newWindow(), timeout);
-
UiObject2.scrollUntil(@NonNull Direction direction, @NonNull Condition<Object, U> condition)
: לדוגמה, כדי לגלול למטה עד שמופיע אובייקט חדש, קוראים ל-object.scrollUntil(Direction.DOWN, Until.hasObject(By.text('new_obj')));
-
UiObject2.scrollUntil(@NonNull Direction direction, @NonNull EventCondition<U> condition)
: לדוגמה, כדי לגלול למטה עד הסוף, קוראים ל-object.scrollUntil(Direction.DOWN, Until.scrollFinished(Direction.DOWN));
קטע הקוד הבא מראה איך להשתמש ב-UI Automator כדי להשבית את מצב 'נא לא להפריע' בהגדרות המערכת באמצעות השיטה performActionAndWait()
שמחכה למעברים:
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.