UI Automator היא מסגרת לבדיקת ממשק משתמש שמתאימה לבדיקת ממשק משתמש פונקציונלי באפליקציות שונות, במערכת ובאפליקציות מותקנות. ממשקי ה-API של UI Automator מאפשרים לכם לקיים אינטראקציה עם רכיבים גלויים במכשיר, ללא קשר ל-Activity
שנמצא בחזית. כך תוכלו לבצע פעולות כמו פתיחת תפריט ההגדרות או מרכז האפליקציות במכשיר לבדיקה. אפשר לחפש רכיב בממשק המשתמש באמצעות מתארים נוחים, כמו הטקסט שמוצג ברכיב או תיאור התוכן שלו.
מסגרת הבדיקה של UI Automator היא ממשק API שמבוסס על מכשירי מדידה, והיא פועלת עם מפעיל הבדיקות AndroidJUnitRunner
. הוא מתאים לכתיבה של בדיקות אוטומטיות מסוג תיבת שחור, שבהן קוד הבדיקה לא מסתמך על פרטי ההטמעה הפנימיים של אפליקציית היעד.
התכונות העיקריות של מסגרת הבדיקה של UI Automator כוללות את האפשרויות הבאות:
- ממשק API לאחזור פרטי המצב ולביצוע פעולות במכשיר היעד. מידע נוסף זמין במאמר גישה למצב המכשיר.
- ממשקי API שתומכים בבדיקת ממשק המשתמש של אפליקציות שונות. מידע נוסף זמין במאמר ממשקי API של UI Automator.
גישה למצב המכשיר
מסגרת הבדיקה של UI Automator מספקת מחלקה UiDevice
כדי לגשת למכשיר שבו פועלת אפליקציית היעד ולבצע בו פעולות. אפשר להפעיל את השיטות שלו כדי לגשת למאפייני המכשיר, כמו הכיוון הנוכחי או גודל המסך. באמצעות הכיתה UiDevice
אפשר גם לבצע את הפעולות הבאות:
- שינוי סיבוב המכשיר.
- לוחצים על מקשי חומרה, כמו 'הגברת עוצמת הקול'.
- לוחצים על הלחצנים 'חזרה', 'דף הבית' או 'תפריט'.
- פותחים את לוח ההתראות.
- מצלמים צילום מסך של החלון הנוכחי.
לדוגמה, כדי לדמות לחיצה על הלחצן הראשי, צריך להפעיל את השיטה UiDevice.pressHome()
.
ממשקי API של UI Automator
ממשקי ה-API של UI Automator מאפשרים לכתוב בדיקות חזקות בלי שתצטרכו לדעת על פרטי ההטמעה של האפליקציה שאליה אתם מטרגטים. אפשר להשתמש בממשקי ה-API האלה כדי לתעד רכיבי ממשק משתמש ולבצע בהם פעולות שונות במספר אפליקציות:
UiObject2
: מייצג אלמנט בממשק המשתמש שגלוי במכשיר.BySelector
: מציינים קריטריונים להתאמה של רכיבי ממשק המשתמש.By
: יצירתBySelector
באופן תמציתי.Configurator
: מאפשר להגדיר פרמטרים מרכזיים להרצת בדיקות של UI Automator.
לדוגמה, הקוד הבא מראה איך אפשר לכתוב סקריפט בדיקה שפותח את אפליקציית Gmail במכשיר:
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.pressHome() val gmail: UiObject2 = device.findObject(By.text("Gmail")) // Perform a click and wait until the app is opened. val opened: Boolean = gmail.clickAndWait(Until.newWindow(), 3000) assertThat(opened).isTrue()
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.pressHome(); UiObject2 gmail = device.findObject(By.text("Gmail")); // Perform a click and wait until the app is opened. Boolean opened = gmail.clickAndWait(Until.newWindow(), 3000); assertTrue(opened);
הגדרת UI Automator
לפני יצירת בדיקת ממשק המשתמש באמצעות UI Automator, חשוב להגדיר את המיקום של קוד המקור של הבדיקה ואת יחסי התלות בפרויקט, כפי שמתואר במאמר הגדרת פרויקט ל-AndroidX Test.
בקובץ build.gradle
של מודול האפליקציה ל-Android, צריך להגדיר הפניה לספריית UI Automator:
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
, לוחצים על הלחצן צילום מסך של המכשיר. - מעבירים את העכבר מעל קובץ snapshot בחלונית הימנית כדי לראות את רכיבי ממשק המשתמש שזוהו באמצעות הכלי
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 ועל שימוש בהצהרות נכוֹנוּת (assertions) ובהערות (annotations) של JUnit 4 זמין במאמר יצירת כיתה של בדיקת יחידה עם כלי למדידת ביצועים.
מוסיפים את ההערה @RunWith(AndroidJUnit4.class) בתחילת ההגדרה של הכיתה לבדיקה. צריך גם לציין את הכיתה AndroidJUnitRunner, שסופקת ב-AndroidX Test, בתור הכלי שמריץ את הבדיקות כברירת מחדל. שלב זה מתואר בפירוט רב יותר בקטע הרצת בדיקות של UI Automator במכשיר או במהדמה.
מטמיעים את מודל התכנות הבא בכיתה של בדיקת UI Automator:
- כדי לקבל גישה למכשיר שרוצים לבדוק, צריך לקבל אובייקט
UiDevice
על ידי קריאה ל-method getInstance() והעברת אובייקט Instrumentation כארגומנטים. - כדי לקבל אובייקט
UiObject2
ולגשת לרכיב בממשק המשתמש שמוצג במכשיר (לדוגמה, התצוגה הנוכחית בחזית), צריך לבצע קריאה לשיטה findObject(). - כדי לדמות אינטראקציה ספציפית של משתמש ברכיב ממשק המשתמש הזה, קוראים לשיטה
UiObject2
. לדוגמה, קוראים ל-scrollUntil() כדי לגלול, ול-setText() כדי לערוך שדה טקסט. אפשר לקרוא לממשקי ה-API בשלבים 2 ו-3 שוב ושוב לפי הצורך כדי לבדוק אינטראקציות מורכבות יותר של משתמשים שכוללות כמה רכיבים של ממשק המשתמש או רצפים של פעולות של משתמשים. - בודקים שממשק המשתמש משקף את המצב או את ההתנהגות הצפויים, אחרי ביצוע האינטראקציות האלה עם המשתמשים.
השלבים האלה מוסברים בהרחבה בקטעים הבאים.
גישה לרכיבי ממשק המשתמש
האובייקט UiDevice
הוא הדרך העיקרית לגשת למצב של המכשיר ולבצע בו שינויים. בבדיקה, אפשר להפעיל שיטות של UiDevice
כדי לבדוק את המצב של מאפיינים שונים, כמו הכיוון הנוכחי או גודל המסך.
אפשר להשתמש באובייקט UiDevice
בבדיקה כדי לבצע פעולות ברמת המכשיר, כמו לאלץ את המכשיר לבצע סיבוב ספציפי, ללחוץ על לחצני החומרה של D-pad וללחוץ על לחצני דף הבית והתפריט.
מומלץ להתחיל את הבדיקה ממסך הבית של המכשיר. במסך הבית (או במיקום אחר שבחרתם במכשיר), אפשר להפעיל את השיטות שסופקו על ידי UI Automator API כדי לבחור רכיבי ממשק משתמש ספציפיים ולבצע איתם פעולות.
קטע הקוד הבא מראה איך הבדיקה יכולה לקבל מופע של UiDevice
ולבצע סימולציה של לחיצה על לחצן הבית:
import org.junit.Before import androidx.test.runner.AndroidJUnit4 import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.By import androidx.test.uiautomator.Until ... private const val BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample" private const val LAUNCH_TIMEOUT = 5000L private const val STRING_TO_BE_TYPED = "UiAutomator" @RunWith(AndroidJUnit4::class) @SdkSuppress(minSdkVersion = 18) class ChangeTextBehaviorTest2 { private lateinit var device: UiDevice @Before fun startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) // Start from the home screen device.pressHome() // Wait for launcher val launcherPackage: String = device.launcherPackageName assertThat(launcherPackage, notNullValue()) device.wait( Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT ) // Launch the app val context = ApplicationProvider.getApplicationContext<Context>() val intent = context.packageManager.getLaunchIntentForPackage( BASIC_SAMPLE_PACKAGE).apply { // Clear out any previous instances addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } context.startActivity(intent) // Wait for the app to appear device.wait( Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT ) } }
import org.junit.Before; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.By; import androidx.test.uiautomator.Until; ... @RunWith(AndroidJUnit4.class) @SdkSuppress(minSdkVersion = 18) public class ChangeTextBehaviorTest { private static final String BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample"; private static final int LAUNCH_TIMEOUT = 5000; private static final String STRING_TO_BE_TYPED = "UiAutomator"; private UiDevice device; @Before public void startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); // Start from the home screen device.pressHome(); // Wait for launcher final String launcherPackage = device.getLauncherPackageName(); assertThat(launcherPackage, notNullValue()); device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); // Launch the app Context context = ApplicationProvider.getApplicationContext(); final Intent intent = context.getPackageManager() .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE); // Clear out any previous instances intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(intent); // Wait for the app to appear device.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT); } }
בדוגמה, ההצהרה @SdkSuppress(minSdkVersion = 18) עוזרת לוודא שהבדיקות יפעלו רק במכשירים עם Android 4.3 (רמת API 18) ואילך, כפי שנדרש במסגרת UI Automator.
משתמשים ב-method findObject()
כדי לאחזר UiObject2
שמייצג תצוגה שתואמת לקריטריונים של בורר נתון. תוכלו לעשות שימוש חוזר במכונות UiObject2
שיצרתם בחלקים אחרים של בדיקת האפליקציה, לפי הצורך.
חשוב לזכור ש-UI Automator Framework מחפש התאמה במסך הנוכחי בכל פעם שבבדיקה נעשה שימוש במכונה של UiObject2
כדי ללחוץ על רכיב בממשק המשתמש או לשלוח שאילתה לנכס.
קטע הקוד הבא מראה איך הבדיקה עשויה ליצור מכונות UiObject2
שמייצגות לחצן ביטול ולחצן אישור באפליקציה.
val okButton: UiObject2 = device.findObject( By.text("OK").clazz("android.widget.Button") ) // Simulate a user-click on the OK button, if found. if (okButton != null) { okButton.click() }
UiObject2 okButton = device.findObject( By.text("OK").clazz("android.widget.Button") ); // Simulate a user-click on the OK button, if found. if (okButton != null) { okButton.click(); }
ציון בורר
כדי לגשת לרכיב UI ספציפי באפליקציה, משתמשים בכיתה By
כדי ליצור מופע של BySelector
. BySelector
מייצג שאילתה לרכיבים ספציפיים בממשק המשתמש המוצג.
אם נמצא יותר מאלמנט תואם אחד, האלמנט התואם הראשון בהיררכיית הפריסה מוחזר כיעד UiObject2
. כשיוצרים נכס BySelector
, אפשר לשרשר כמה נכסים כדי לחדד את החיפוש. אם לא נמצא רכיב ממשק משתמש תואם, המערכת מחזירה את הערך null
.
אפשר להשתמש ב-method hasChild()
או ב-method hasDescendant()
כדי להטמיע מספר מכונות BySelector
. לדוגמה, בדוגמת הקוד הבאה מוסבר איך אפשר לציין בחיפוש של הבדיקה את ListView
הראשון שיש לו רכיב UI צאצא עם מאפיין הטקסט.
val listView: UiObject2 = device.findObject( By.clazz("android.widget.ListView") .hasChild( By.text("Apps") ) )
UiObject2 listView = device.findObject( By.clazz("android.widget.ListView") .hasChild( By.text("Apps") ) );
כדאי לציין את מצב האובייקט בקריטריונים של הבורר. לדוגמה, אם רוצים לבחור רשימה של כל הרכיבים המסומנים כדי לבטל את הסימון שלהם, צריך להפעיל את השיטה checked()
עם הארגומנט true.
ביצוע פעולות
אחרי שהבדיקה מקבלת אובייקט UiObject2
, אפשר להפעיל את השיטות בכיתה UiObject2
כדי לבצע אינטראקציות של משתמשים ברכיב ממשק המשתמש שמיוצג על ידי האובייקט הזה. אפשר לציין פעולות כמו:
click()
: לחיצה במרכז הגבולות הגלויים של רכיב ממשק המשתמש.drag()
: גוררים את האובייקט הזה לקואורדינטות שרירותיות.setText()
: מגדיר את הטקסט בשדה שניתן לעריכה, אחרי שמוחקים את התוכן של השדה. לעומת זאת, השיטהclear()
מנקה את הטקסט הקיים בשדה שניתן לעריכה.swipe()
: ביצוע פעולת ההחלקה בכיוון שצוין.scrollUntil()
: ביצוע פעולת הגלילה בכיוון שצוין עד שתתנאיCondition
אוEventCondition
מתקיים.
מסגרת הבדיקה של UI Automator מאפשרת לשלוח Intent או להפעיל Activity בלי להשתמש בפקודות מעטפת, על ידי קבלת אובייקט Context דרך getContext()
.
קטע הקוד הבא מראה איך אפשר להשתמש בIntent בבדיקה כדי להפעיל את האפליקציה שנבדקת. הגישה הזו שימושית אם אתם רוצים לבדוק רק את אפליקציית המחשבון ולא את מרכז האפליקציות.
fun setUp() { ... // Launch a simple calculator app val context = getInstrumentation().context val intent = context.packageManager.getLaunchIntentForPackage(CALC_PACKAGE).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } // Clear out any previous instances context.startActivity(intent) device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT) }
public void setUp() { ... // Launch a simple calculator app Context context = getInstrumentation().getContext(); Intent intent = context.getPackageManager() .getLaunchIntentForPackage(CALC_PACKAGE); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances context.startActivity(intent); device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT); }
אימות התוצאות
InstrumentationTestCase הוא תת-מחלקה של TestCase, כך שאפשר להשתמש בשיטות Assert הסטנדרטיות של JUnit כדי לבדוק שמרכיבי ממשק המשתמש באפליקציה מחזירים את התוצאות הצפויות.
קטע הקוד הבא מראה איך הבדיקה יכולה לאתר כמה לחצנים באפליקציית מחשבון, ללחוץ עליהם לפי הסדר ולאמת שהתוצאה הנכונה מוצגת.
private const val CALC_PACKAGE = "com.myexample.calc" fun testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(By.res(CALC_PACKAGE, "two")).click() device.findObject(By.res(CALC_PACKAGE, "plus")).click() device.findObject(By.res(CALC_PACKAGE, "three")).click() device.findObject(By.res(CALC_PACKAGE, "equals")).click() // Verify the result = 5 val result: UiObject2 = device.findObject(By.res(CALC_PACKAGE, "result")) assertEquals("5", result.text) }
private static final String CALC_PACKAGE = "com.myexample.calc"; public void testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(By.res(CALC_PACKAGE, "two")).click(); device.findObject(By.res(CALC_PACKAGE, "plus")).click(); device.findObject(By.res(CALC_PACKAGE, "three")).click(); device.findObject(By.res(CALC_PACKAGE, "equals")).click(); // Verify the result = 5 UiObject2 result = device.findObject(By.res(CALC_PACKAGE, "result")); assertEquals("5", result.getText()); }
הרצת בדיקות של UI Automator במכשיר או באמולטור
אפשר להריץ בדיקות של UI Automator מ-Android Studio או משורת הפקודה. חשוב לציין את AndroidJUnitRunner
בתור הכלי ברירת המחדל להפעלת כלי המדידה בפרויקט.
דוגמאות נוספות
אינטראקציה עם ממשק המשתמש של המערכת
UI Automator יכול לקיים אינטראקציה עם כל מה שמופיע במסך, כולל רכיבי מערכת מחוץ לאפליקציה, כפי שמוצג בקטעי הקוד הבאים:
// Opens the System Settings. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.executeShellCommand("am start -a android.settings.SETTINGS")
// Opens the System Settings. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.executeShellCommand("am start -a android.settings.SETTINGS");
// Opens the notification shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.openNotification()
// Opens the notification shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.openNotification();
// Opens the Quick Settings shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.openQuickSettings()
// Opens the Quick Settings shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.openQuickSettings();
// Get the system clock. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) UiObject2 clock = device.findObject(By.res("com.android.systemui:id/clock")) print(clock.getText())
// Get the system clock. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); UiObject2 clock = device.findObject(By.res("com.android.systemui:id/clock")); print(clock.getText());
המתנה למעברים

מעברים בין מסכים עשויים להימשך זמן מה, וקשה לחזות את משך הזמן שלהם, לכן כדאי להגדיר ל-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()
שמחכה למעברים:
@Test @SdkSuppress(minSdkVersion = 21) @Throws(Exception::class) fun turnOffDoNotDisturb() { device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.performActionAndWait({ try { device.executeShellCommand("am start -a android.settings.SETTINGS") } catch (e: IOException) { throw RuntimeException(e) } }, Until.newWindow(), 1000) // Check system settings has been opened. Assert.assertTrue(device.hasObject(By.pkg("com.android.settings"))) // Scroll the settings to the top and find Notifications button var scrollableObj: UiObject2 = device.findObject(By.scrollable(true)) scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP)) val notificationsButton = scrollableObj.findObject(By.text("Notifications")) // Click the Notifications button and wait until a new window is opened. device.performActionAndWait({ notificationsButton.click() }, Until.newWindow(), 1000) scrollableObj = device.findObject(By.scrollable(true)) // Scroll down until it finds a Do Not Disturb button. val doNotDisturb = scrollableObj.scrollUntil( Direction.DOWN, Until.findObject(By.textContains("Do Not Disturb")) ) device.performActionAndWait({ doNotDisturb.click() }, Until.newWindow(), 1000) // Turn off the Do Not Disturb. val turnOnDoNotDisturb = device.findObject(By.text("Turn on now")) turnOnDoNotDisturb?.click() Assert.assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000)) }
@Test @SdkSuppress(minSdkVersion = 21) public void turnOffDoNotDisturb() throws Exception{ device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.performActionAndWait(() -> { try { device.executeShellCommand("am start -a android.settings.SETTINGS"); } catch (IOException e) { throw new RuntimeException(e); } }, Until.newWindow(), 1000); // Check system settings has been opened. assertTrue(device.hasObject(By.pkg("com.android.settings"))); // Scroll the settings to the top and find Notifications button UiObject2 scrollableObj = device.findObject(By.scrollable(true)); scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP)); UiObject2 notificationsButton = scrollableObj.findObject(By.text("Notifications")); // Click the Notifications button and wait until a new window is opened. device.performActionAndWait(() -> notificationsButton.click(), Until.newWindow(), 1000); scrollableObj = device.findObject(By.scrollable(true)); // Scroll down until it finds a Do Not Disturb button. UiObject2 doNotDisturb = scrollableObj.scrollUntil(Direction.DOWN, Until.findObject(By.textContains("Do Not Disturb"))); device.performActionAndWait(()-> doNotDisturb.click(), Until.newWindow(), 1000); // Turn off the Do Not Disturb. UiObject2 turnOnDoNotDisturb = device.findObject(By.text("Turn on now")); if(turnOnDoNotDisturb != null) { turnOnDoNotDisturb.click(); } assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000)); }
מקורות מידע נוספים
למידע נוסף על השימוש ב-UI Automator בבדיקות של Android, תוכלו לעיין במקורות המידע הבאים.
מסמכי עזר:
דוגמיות
- BasicSample: דוגמה בסיסית ל-UI Automator.