كتابة الاختبارات المبرمجة باستخدام واجهة المستخدم التلقائية

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

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

تشمل الميزات الرئيسية لإطار عمل اختبار واجهة المستخدم التلقائية ما يلي:

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

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

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

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

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

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

  • UiObject2: يمثل عنصر واجهة مستخدم مرئيًا على الجهاز.
  • BySelector: يحدّد معايير مطابقة عناصر واجهة المستخدم.
  • By: تنشئ BySelector بطريقة موجزة.
  • Configurator: يتيح لك هذا الخيار ضبط المَعلمات الرئيسية لإجراء اختبارات واجهة المستخدم 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، احرص على ضبط موقع رمز مصدر الاختبار وتبعيات المشروع، كما هو موضّح في إعداد المشروع على AndroidX Test.

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

Kotlin

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

رائع

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

لتحسين اختبار 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، يمكنك الاطّلاع على واجهة المستخدم.

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

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

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

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

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

إنشاء فئة اختبار لواجهة المستخدم

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

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

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

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

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

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

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

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

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

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

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

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

يتيح لك إطار عمل اختبار واجهة المستخدم Automator إرسال عنصر Intent أو بدء نشاط بدون استخدام أوامر واجهة الأوامر، من خلال الحصول على عنصر السياق من خلال 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);
}

التحقّق من النتائج

يوسع ElementationTestCase حالة TestCase، بحيث يمكنك استخدام طرق JUnit Assert القياسية لاختبار أن مكوّنات واجهة المستخدم في التطبيق تعرض النتائج المتوقعة.

يعرض المقتطف التالي كيف يمكن للاختبار تحديد موقع عدة أزرار في تطبيق الآلة الحاسبة، ثم انقر عليها بالترتيب، ثم تحقق من عرض النتيجة الصحيحة.

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

إجراء اختبارات واجهة المستخدم التلقائية على جهاز أو محاكي

يمكنك إجراء اختبارات واجهة المستخدم 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());

انتظار عمليات النقل

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

يمكن أن تستغرق انتقالات الشاشة بعض الوقت والتنبؤ بمدتها غير موثوق، لذا يجب أن تطلب من واجهة المستخدم 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، يُرجى الرجوع إلى الموارد التالية.

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

عيّنات

  • Basicعيّن: نموذج "أداة التشغيل الآلي لواجهة المستخدم الأساسية".