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

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

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

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

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

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

يوفّر إطار عمل اختبار 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") }

أنيق

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) في ضمان عدم تشغيل الاختبارات إلا على الأجهزة التي تعمل بنظام التشغيل Android 4.3 (مستوى واجهة برمجة التطبيقات 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 أو تشغيل Activity بدون استخدام أوامر 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، لذا يمكنك استخدام طُرق 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());
}

تشغيل اختبارات 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، يُرجى الاطّلاع على المراجع التالية.

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

نماذج