كتابة اختبارات مبرمَجة باستخدام UI Automator (إرشادات قديمة)

‫UI Automator هو إطار عمل لاختبار واجهة المستخدم، وهو مناسب لاختبار وظائف واجهة المستخدم في التطبيقات المختلفة على مستوى النظام والتطبيقات المثبَّتة. تتيح لك واجهات برمجة التطبيقات UI Automator التفاعل مع العناصر المرئية على الجهاز، بغض النظر عن Activity الذي يكون في المقدّمة، ما يتيح لك تنفيذ عمليات مثل فتح قائمة "الإعدادات" أو مشغّل التطبيقات على جهاز الاختبار. يمكن أن يبحث الاختبار عن أحد عناصر واجهة المستخدم باستخدام أوصاف مناسبة، مثل النص المعروض في هذا العنصر أو وصف المحتوى الخاص به.

إطار عمل الاختبار UI Automator هو واجهة برمجة تطبيقات تستند إلى أدوات، وتعمل مع AndroidJUnitRunner لتشغيل الاختبار. وهي مناسبة تمامًا لكتابة اختبارات آلية على شكل مربّع غير شفاف، حيث لا يعتمد رمز الاختبار على تفاصيل التنفيذ الداخلية للتطبيق المستهدف.

تشمل الميزات الرئيسية لإطار عمل اختبار UI Automator ما يلي:

  • واجهة برمجة تطبيقات لاسترداد معلومات الحالة وتنفيذ عمليات على الجهاز المستهدف لمزيد من المعلومات، يُرجى الاطّلاع على الوصول إلى حالة الجهاز.
  • واجهات برمجة التطبيقات التي تتيح اختبار واجهة المستخدم عبر التطبيقات لمزيد من المعلومات، يُرجى الاطّلاع على واجهات برمجة تطبيقات UI Automator.

الوصول إلى حالة الجهاز

يوفّر إطار عمل الاختبار UI Automator فئة UiDevice للوصول إلى الجهاز الذي يتم تشغيل التطبيق المستهدَف عليه وتنفيذ عمليات عليه. يمكنك استدعاء طُرقها للوصول إلى خصائص الجهاز، مثل الاتجاه الحالي أو حجم الشاشة. يتيح لك صف UiDevice أيضًا تنفيذ الإجراءات التالية:

  1. تغيير اتجاه الجهاز
  2. اضغط على مفاتيح الأجهزة، مثل "رفع مستوى الصوت".
  3. اضغط على زر الرجوع أو زر الشاشة الرئيسية أو زر القائمة.
  4. افتح مركز الإشعارات.
  5. التقاط لقطة شاشة للنافذة الحالية

على سبيل المثال، لمحاكاة الضغط على زر الشاشة الرئيسية، استدعِ طريقة UiDevice.pressHome().

واجهات برمجة تطبيقات UI Automator

تتيح لك واجهات برمجة التطبيقات UI Automator كتابة اختبارات قوية بدون الحاجة إلى معرفة تفاصيل تنفيذ التطبيق الذي تستهدفه. يمكنك استخدام واجهات برمجة التطبيقات هذه لالتقاط عناصر واجهة المستخدم ومعالجتها في تطبيقات متعددة:

  • 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 Automator، احرص على ضبط موقع رمز المصدر للاختبار وتبعيات المشروع، كما هو موضّح في مقالة إعداد المشروع لأداة AndroidX Test.

في ملف build.gradle لوحدة تطبيق Android، يجب ضبط مرجع اعتمادية على مكتبة UI Automator:

Kotlin

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

Groovy

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

لتحسين اختبار UI Automator، عليك أولاً فحص عناصر واجهة المستخدم في التطبيق المستهدَف والتأكّد من إمكانية الوصول إليها. يتم وصف نصائح التحسين هذه في القسمَين التاليَين.

فحص واجهة المستخدم على جهاز

قبل تصميم الاختبار، افحص مكوّنات واجهة المستخدم المرئية على الجهاز. لضمان إمكانية وصول اختبارات UI Automator إلى هذه المكوّنات، تأكَّد من أنّ هذه المكوّنات تتضمّن تصنيفات نصية مرئية أو قيم android:contentDescription أو كليهما.

توفّر أداة uiautomatorviewer واجهة مرئية ملائمة لفحص التسلسل الهرمي للتصميم وعرض خصائص عناصر واجهة المستخدم الظاهرة في مقدّمة الجهاز. تتيح لك هذه المعلومات إنشاء اختبارات أكثر دقة باستخدام UI Automator. على سبيل المثال، يمكنك إنشاء أداة اختيار لعناصر واجهة المستخدم تتطابق مع سمة مرئية معيّنة.

لإطلاق أداة uiautomatorviewer، اتّبِع الخطوات التالية:

  1. شغِّل التطبيق المستهدف على جهاز فعلي.
  2. وصِّل الجهاز بجهاز التطوير.
  3. افتح نافذة أوامر طرفية وانتقِل إلى الدليل <android-sdk>/tools/.
  4. شغِّل الأداة باستخدام الأمر التالي:
 $ uiautomatorviewer

للاطّلاع على خصائص واجهة المستخدم لتطبيقك، اتّبِع الخطوات التالية:

  1. في واجهة uiautomatorviewer، انقر على الزر لقطة شاشة الجهاز.
  2. مرِّر مؤشر الماوس فوق اللقطة في اللوحة اليمنى للاطّلاع على عناصر واجهة المستخدم التي حدّدتها أداة uiautomatorviewer. يتم عرض الخصائص في اللوحة اليمنى السفلية، ويتم عرض التسلسل الهرمي للتصميم في اللوحة اليمنى العلوية.
  3. يمكنك اختياريًا النقر على الزر تبديل عقد NAF لعرض عناصر واجهة المستخدم التي لا يمكن الوصول إليها باستخدام UI Automator. قد تتوفر معلومات محدودة فقط لهذه المكوّنات.

للتعرّف على الأنواع الشائعة لمكوّنات واجهة المستخدم التي يوفّرها Android، راجِع واجهة المستخدم.

التأكّد من إمكانية الوصول إلى نشاطك

يحقّق إطار اختبار UI Automator أداءً أفضل على التطبيقات التي نفّذت ميزات تسهيل الاستخدام في Android. عند استخدام عناصر واجهة مستخدم من النوع View أو فئة فرعية من View من حزمة تطوير البرامج (SDK)، لن تحتاج إلى تنفيذ ميزة تسهيل الاستخدام، لأنّ هذه الفئات قد نفّذت ذلك نيابةً عنك.

ومع ذلك، تستخدم بعض التطبيقات عناصر واجهة مستخدم مخصّصة لتوفير تجربة مستخدم أكثر ثراءً. ولن توفّر هذه العناصر إمكانية الوصول التلقائي. إذا كان تطبيقك يتضمّن مثيلات لفئة فرعية من View ليست من حزمة SDK، احرص على إضافة ميزات تسهيل الاستخدام إلى هذه العناصر من خلال إكمال الخطوات التالية:

  1. أنشئ فئة ملموسة توسّع ExploreByTouchHelper.
  2. اربط مثيلاً لفئتك الجديدة بعنصر واجهة مستخدم مخصّص محدّد من خلال استدعاء setAccessibilityDelegate()‎.

للحصول على إرشادات إضافية حول إضافة ميزات تسهيل الاستخدام إلى عناصر العرض المخصّص، يُرجى الاطّلاع على إنشاء طرق عرض مخصّصة تسهّل الاستخدام. لمزيد من المعلومات حول أفضل الممارسات العامة المتعلّقة بتسهيل الاستخدام على Android، يُرجى الاطّلاع على مقالة تسهيل استخدام التطبيقات.

إنشاء فئة اختبار UI Automator

يجب كتابة فئة اختبار UI Automator بالطريقة نفسها التي تُكتب بها فئة اختبار JUnit 4. لمزيد من المعلومات حول إنشاء فئات اختبار JUnit 4 واستخدام تأكيدات وتعليقات توضيحية JUnit 4، راجِع إنشاء فئة اختبار وحدة مزوَّدة بأدوات.

أضِف التعليق التوضيحي @RunWith(AndroidJUnit4.class) في بداية تعريف فئة الاختبار. عليك أيضًا تحديد فئة AndroidJUnitRunner، المضمّنة في AndroidX Test، بصفتها أداة تشغيل الاختبار التلقائية. يتم وصف هذه الخطوة بمزيد من التفصيل في مقالة تشغيل اختبارات UI Automator على جهاز أو محاكي.

نفِّذ نموذج البرمجة التالي في فئة اختبار UI Automator:

  1. احصل على كائن UiDevice للوصول إلى الجهاز الذي تريد اختباره، وذلك من خلال استدعاء الطريقة getInstance() وتمرير كائن Instrumentation إليه كمعلَمة.
  2. احصل على الكائن UiObject2 للوصول إلى أحد مكوّنات واجهة المستخدم المعروضة على الجهاز (مثل العرض الحالي في المقدّمة)، وذلك من خلال استدعاء الطريقة findObject().
  3. محاكاة تفاعل مستخدم معيّن لتنفيذه على مكوّن واجهة المستخدم هذا، وذلك من خلال استدعاء طريقة UiObject2، مثل استدعاء scrollUntil() للتمرير وsetText() لتعديل حقل نصي يمكنك استدعاء واجهات برمجة التطبيقات في الخطوتين 2 و3 بشكل متكرّر حسب الحاجة لاختبار تفاعلات المستخدمين الأكثر تعقيدًا التي تتضمّن عدّة مكوّنات في واجهة المستخدم أو تسلسلات من إجراءات المستخدمين.
  4. تأكَّد من أنّ واجهة المستخدم تعكس الحالة أو السلوك المتوقّعَين بعد تنفيذ تفاعلات المستخدم هذه.

يتم تناول هذه الخطوات بمزيد من التفصيل في الأقسام أدناه.

الوصول إلى مكوّنات واجهة المستخدم

عنصر UiDevice هو الطريقة الأساسية للوصول إلى حالة الجهاز وتعديلها. في اختباراتك، يمكنك استدعاء طرق UiDevice للتحقّق من حالة الخصائص المختلفة، مثل الاتجاه الحالي أو حجم الشاشة. يمكن أن يستخدم الاختبار العنصر UiDevice لتنفيذ إجراءات على مستوى الجهاز، مثل فرض تدوير الجهاز بشكل معيّن، والضغط على أزرار لوحة التحكّم، والضغط على زرَي "الصفحة الرئيسية" و"القائمة".

من الممارسات الجيدة أن تبدأ الاختبار من الشاشة الرئيسية للجهاز. من الشاشة الرئيسية (أو أي موقع بدء آخر اخترته في الجهاز)، يمكنك استدعاء الطرق التي توفّرها واجهة برمجة التطبيقات UI Automator لاختيار عناصر معيّنة في واجهة المستخدم والتفاعل معها.

يوضّح مقتطف الرمز البرمجي التالي كيف يمكن أن يحصل الاختبار على مثيل من 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) في ضمان عدم تشغيل الاختبارات إلا على الأجهزة التي تعمل بالإصدار 4.3 من نظام التشغيل Android (المستوى 18 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، وذلك على النحو المطلوب من إطار عمل UI Automator.

استخدِم طريقة findObject() لاسترداد UiObject2 يمثّل عرضًا يطابق معايير أداة اختيار معيّنة. يمكنك إعادة استخدام UiObject2 الآلات الافتراضية التي أنشأتها في أجزاء أخرى من اختبار تطبيقك، حسب الحاجة. يُرجى العِلم أنّ إطار عمل اختبار UI Automator يبحث في الشاشة الحالية عن تطابق في كل مرة يستخدم فيها الاختبار مثيلاً من 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.

يمكنك استخدام الطريقتَين hasChild() أو hasDescendant() لتضمين عدة مثيلات من BySelector. على سبيل المثال، يوضّح نموذج الرمز البرمجي التالي كيف يمكن أن يحدّد الاختبار عملية بحث للعثور على أول ListView يتضمّن عنصر واجهة مستخدم فرعيًا مع السمة النصية.

Kotlin

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

Java

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

قد يكون من المفيد تحديد حالة العنصر في معايير أداة الاختيار. على سبيل المثال، إذا أردت اختيار قائمة بجميع العناصر المحدّدة لتتمكّن من إزالة تحديدها، استخدِم طريقة checked() مع ضبط الوسيطة على "صحيح".

تنفيذ الإجراءات

بعد أن يحصل الاختبار على عنصر UiObject2، يمكنك استدعاء الطرق في فئة UiObject2 لتنفيذ تفاعلات المستخدم مع عنصر واجهة المستخدم الذي يمثّله هذا العنصر. يمكنك تحديد هذه الإجراءات على النحو التالي:

  • click() : ينقر على وسط الحدود المرئية لعنصر واجهة المستخدم.
  • drag() : يسحب هذا العنصر إلى إحداثيات عشوائية.
  • setText() : تضبط هذه السمة النص في حقل قابل للتعديل، وذلك بعد محو محتوى الحقل. في المقابل، تمحو الطريقة clear() النص الحالي في حقل قابل للتعديل.
  • استبدِل swipe() بإجراء التمرير السريع في الاتجاه المحدّد.
  • scrollUntil(): ينفّذ إجراء التمرير في الاتجاه المحدّد إلى أن يتم استيفاء Condition أو EventCondition.

يتيح لك إطار عمل الاختبار UI Automator إرسال Intent أو تشغيل نشاط بدون استخدام أوامر shell، وذلك من خلال الحصول على عنصر 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، لذا يمكنك استخدام طرق 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 أو من سطر الأوامر. تأكَّد من تحديد 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());

انتظار الانتقالات

إيقاف وضع &quot;عدم الإزعاج&quot;
الشكل 1. توقف أداة UI Automator وضع "عدم الإزعاج" على جهاز اختباري.

قد تستغرق عمليات انتقال الشاشة بعض الوقت، ولا يمكن توقُّع مدتها بدقة، لذا عليك استخدام UI Automator لانتظار اكتمال العمليات. توفّر أداة UI Automator عدة طرق لإجراء ذلك، وهي:

يوضّح مقتطف الرمز التالي كيفية استخدام UI Automator لإيقاف وضع "عدم الإزعاج" في إعدادات النظام باستخدام الطريقة performActionAndWait() التي تنتظر عمليات الانتقال:

Kotlin

@Test
@SdkSuppress(minSdkVersion = 21)
@Throws(Exception::class)
fun turnOffDoNotDisturb() {
    device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
    device.performActionAndWait({
        try {
            device.executeShellCommand("am start -a android.settings.SETTINGS")
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }, Until.newWindow(), 1000)
    // Check system settings has been opened.
    Assert.assertTrue(device.hasObject(By.pkg("com.android.settings")))

    // Scroll the settings to the top and find Notifications button
    var scrollableObj: UiObject2 = device.findObject(By.scrollable(true))
    scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP))
    val notificationsButton = scrollableObj.findObject(By.text("Notifications"))

    // Click the Notifications button and wait until a new window is opened.
    device.performActionAndWait({ notificationsButton.click() }, Until.newWindow(), 1000)
    scrollableObj = device.findObject(By.scrollable(true))
    // Scroll down until it finds a Do Not Disturb button.
    val doNotDisturb = scrollableObj.scrollUntil(
        Direction.DOWN,
        Until.findObject(By.textContains("Do Not Disturb"))
    )
    device.performActionAndWait({ doNotDisturb.click() }, Until.newWindow(), 1000)
    // Turn off the Do Not Disturb.
    val turnOnDoNotDisturb = device.findObject(By.text("Turn on now"))
    turnOnDoNotDisturb?.click()
    Assert.assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000))
}

Java

@Test
@SdkSuppress(minSdkVersion = 21)
public void turnOffDoNotDisturb() throws Exception{
    device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    device.performActionAndWait(() -> {
        try {
            device.executeShellCommand("am start -a android.settings.SETTINGS");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }, Until.newWindow(), 1000);
    // Check system settings has been opened.
    assertTrue(device.hasObject(By.pkg("com.android.settings")));

    // Scroll the settings to the top and find Notifications button
    UiObject2 scrollableObj = device.findObject(By.scrollable(true));
    scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP));
    UiObject2 notificationsButton = scrollableObj.findObject(By.text("Notifications"));

    // Click the Notifications button and wait until a new window is opened.
    device.performActionAndWait(() -> notificationsButton.click(), Until.newWindow(), 1000);
    scrollableObj = device.findObject(By.scrollable(true));
    // Scroll down until it finds a Do Not Disturb button.
    UiObject2 doNotDisturb = scrollableObj.scrollUntil(Direction.DOWN,
            Until.findObject(By.textContains("Do Not Disturb")));
    device.performActionAndWait(()-> doNotDisturb.click(), Until.newWindow(), 1000);
    // Turn off the Do Not Disturb.
    UiObject2 turnOnDoNotDisturb = device.findObject(By.text("Turn on now"));
    if(turnOnDoNotDisturb != null) {
        turnOnDoNotDisturb.click();
    }
    assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000));
}

مراجع إضافية

لمزيد من المعلومات حول استخدام UI Automator في اختبارات Android، يُرجى الرجوع إلى المراجع التالية.

المستندات المرجعية:

نماذج

  • BasicSample: نموذج أساسي لواجهة مستخدم Automator.