UI Automator هو إطار عمل من Google لاختبار واجهة المستخدم الآلي لتطبيقات Android يعمل على مستوى النظام ويمكنه التفاعل مع عناصر الواجهة خارج تطبيق واحد. على عكس Espresso، UI Automator غير مرتبط بعملية تطبيق معين: يمكنه فتح حوارات النظام، لوحة الإشعارات والتبديل بين التطبيقات. وفقًا لـ Google Android Developers، يستخدم UI Automator Accessibility Service القياسي للوصول إلى شجرة واجهة المستخدم للجهاز.
الرئيسية
UI Automator هو إطار عمل لاختبار واجهة المستخدم الوظيفي لنظام Android يعمل على مستوى نظام التشغيل. يوفر API للوصول إلى أي عنصر على شاشة الجهاز، بغض النظر عن التطبيق الذي ينتمي إليه — بما في ذلك شريط حالة النظام، حوارات الأذونات، الشاشة الرئيسية والتطبيقات الخارجية. هذا يجعله لا غنى عنه لاختبار السيناريوهات التي تتجاوز تطبيقًا واحدًا.
من الناحية المعمارية، يستخدم UI Automator Accessibility Service — نفس الخدمة التي تستخدمها TalkBack وSwitch Access وأدوات الوصول الأخرى. من خلال هذه الخدمة، يحصل الإطار على شجرة مكونات واجهة المستخدم الكاملة للشاشة الحالية ويتيح تنفيذ الإجراءات عليها: النقر، السحب، إدخال النص والضغط المطول.
ظهر UI Automator لأول مرة في Android 4.3 (API 18) ومنذ ذلك الحين أصبح جزءًا من Android Testing Support Library كأداة رسمية من Google للاختبار عبر التطبيقات. في AndroidX Test، يتوفر كقطعة منفصلة androidx.test.uiautomator:uiautomator الإصدار 2.3.0 (2024)، الذي يدعم جميع إصدارات Android من API 18.
مبدأ العمل: يعتمد UI Automator على مسح شجرة إمكانية الوصول للشاشة الحالية. عند استدعاء طريقة findObject(selector)، يجتاز الإطار التسلسل الهرمي للعرض، ويجد أول عنصر يطابق شروط UiSelector، ويعيد UiObject — وكيل للتفاعل مع العرض الفعلي.
يبدأ اختبار UI Automator النموذجي بالحصول على مثيل UiDevice، الذي يمثل الجهاز الفعلي. يوفر UiDevice طرقًا للعثور على العناصر، إدارة ضغطات الأزرار (الصفحة الرئيسية، العودة، الحديثة)، تدوير الشاشة وأخذ لقطات الشاشة. بعد العثور على عنصر عبر UiSelector، يتم تنفيذ الإجراءات على UiObject.
في المثال أدناه، يفتح الاختبار تطبيق الإعدادات، ويجد عنصر «البطارية» بالنص ويضغط عليه. لا يتطلب UI Automator تشغيل نشاط — فهو يعمل مع أي شاشة على الجهاز، بما في ذلك التطبيقات الخارجية.
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// فتح شاشة الإعدادات
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("الإعدادات")), 2000)
// البحث عن عنصر "البطارية" والضغط
val batteryItem = device.findObject(
UiSelector().text("البطارية")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)
UiDevice هي الفئة الرئيسية للتفاعل مع الجهاز. توفر طرقًا للعثور على العناصر، محاكاة ضغطات الأزرار المادية (الصفحة الرئيسية، العودة، القائمة، الصوت)، إدارة الطاقة، أخذ لقطات الشاشة وانتظار حالات شاشة محددة. يتم إنشاء UiDevice مرة واحدة لكل اختبار وإعادة استخدامه لجميع العمليات.
UiSelector هي API مرنة للعثور على عناصر واجهة المستخدم. على عكس Espresso ViewMatchers، لا يتطلب UiSelector تجميعًا — يتم تشكيل شروط البحث من خلال سلسلة من الطرق: text()، className()، description()، resourceId()، index(). يتم دمج الشروط المتعددة تلقائيًا عبر AND المنطقي.
| طريقة UiSelector | الغرض |
|---|---|
| text(String) | البحث بالنص الدقيق للعنصر |
| textContains(String) | البحث بتطابق جزئي للنص |
| resourceId(String) | البحث بمعرف المورد (مثل، com.example:id/button) |
| className(String) | البحث باسم فئة العرض |
| description(String) | البحث بواسطة content-description |
| childSelector(selector) | البحث عن عنصر فرعي داخل حاوية |
عند وجود عدة عناصر على الشاشة بنفس النص، يسمح UiSelector بدمج المعايير: العثور على حاوية بالمعرف، ثم داخلها — عنصر بالنص والصنف. هذا يضمن تحديدًا فريدًا للمكون المطلوب. طريقة childSelector تضيق نطاق البحث إلى حاوية محددة، مما يسرع التنقل في شجرة واجهة المستخدم.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// داخل القائمة، ابحث عن العنصر بالنص "Wi-Fi"
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
الاختبار عبر التطبيقات (بين التطبيقات) هو الميزة الرئيسية التي يختار من أجلها UI Automator. يمكن للإطار التبديل بين التطبيقات، اختبار تسجيل الدخول OAuth عبر المتصفح، التحقق من حوارات النظام (الأذونات، منتقي التطبيقات) والتفاعل مع شريط حالة النظام، لوحة الإشعارات وشاشة القفل.
سيناريو اختبار عبر التطبيقات نموذجي: يفتح التطبيق متصفحًا لتسجيل الدخول OAuth، يدخل المستخدم اسم المستخدم وكلمة المرور، ويعيد المتصفح التوجيه إلى التطبيق. يتبدل UI Automator بين العمليات، ويجد حقول الإدخال في المتصفح، يملؤها ويضغط «تسجيل الدخول».
// انتظار ظهور المتصفح
device.wait(Until.hasObject(
UiSelector().packageName("com.android.chrome")
), 5000)
// البحث عن حقل إدخال البريد الإلكتروني في المتصفح
val emailField = device.findObject(
UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"
يمكن لـ UI Automator التحقق من حوارات النظام وإغلاقها — أذونات الموقع، الإشعارات، الوصول إلى الملفات. هذا مهم جدًا لاختبار سيناريوهات التشغيل الأول عندما يطلب النظام عدة أذونات بالتسلسل. بدون UI Automator، لا يمكن أتمتة هذه السيناريوهات لأن حوارات النظام لا تنتمي إلى عملية التطبيق.
الاختيار بين UI Automator وEspresso يعتمد على سيناريو الاختبار. Espresso محسّن لاختبار تطبيق واحد مع مزامنة تلقائية وحد أدنى من النموذج. UI Automator مناسب للسيناريوهات التي تتطلب التفاعل مع النظام أو المتصفح أو تطبيقات متعددة.
| المعيار | UI Automator | Espresso |
|---|---|---|
| النطاق | الجهاز بالكامل، تطبيقات متعددة | تطبيق واحد |
| المزامنة | يدوية (انتظار، نوم) | تلقائية (مصدر الخمول) |
| السرعة | أبطأ (الوصول عبر الخدمة) | أسرع (يعمل داخل العملية) |
| واجهة النظام | يدعم (الإشعارات، الإعدادات السريعة) | لا يدعم |
| دقة البحث | UiSelector بالسمات | ViewMatchers بالنوع والتسلسل الهرمي |
| الاستقرار | أقل (يعتمد على التوقيت) | أعلى (انتظار تلقائي) |
في الممارسة العملية، غالبًا ما تُستخدم هذه الأطر معًا: يغطي Espresso اختبارات واجهة المستخدم للتطبيق الرئيسي باستقرار عالٍ، بينما يُستخدم UI Automator للسيناريوهات التي تتجاوز حدود التطبيق — تسجيل الدخول OAuth، أذونات النظام، العمل مع مشاركة النية. هذا المزيج يوفر أقصى تغطية لواجهة المستخدم بأقل تكاليف صيانة للاختبارات.
التكامل يتم إضافة UI Automator من خلال إضافة تبعية في build.gradle. الإطار جزء من AndroidX Test ولا يتطلب أذونات إضافية في البيان — يتم تكوين الوصول إلى Accessibility Service تلقائيًا عند تشغيل الاختبار الآلي.
يتضمن الحد الأدنى من التكوين القطعة uiautomator ومشغل الاختبار القياسي AndroidJUnitRunner. توضع اختبارات UI Automator في دليل src/androidTest وتُشغّل على محاكي أو جهاز فعلي يعمل بنظام Android API 18+.
dependencies {
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test:runner:1.6.1")
}
للحصول على مثيل UiDevice، يُستخدم InstrumentationRegistry.getInstrumentation(). يجب إنشاء UiDevice مرة واحدة في طريقة setUp() وإعادة استخدامه عبر جميع اختبارات الفئة للحفاظ على موارد الجهاز. من المهم ملاحظة أن UiDevice ليس آمنًا للخيوط — يجب تنفيذ جميع العمليات في نفس الخيط لطريقة الاختبار. إنشاء UiDevice جديد في كل اختبار يؤدي إلى تكاليف إضافية وإبطاء التنفيذ. يُوصى بإنشاء UiDevice مرة واحدة في طريقة beforeClass وإعادة استخدامه لجميع اختبارات فئة الاختبار.
على عكس Espresso، لا يحتوي UI Automator على مزامنة تلقائية. لانتظار ظهور العناصر، تُستخدم طريقة UiDevice.wait(condition, timeout) مع كائن Until: Until.findObject(selector)، Until.hasObject(selector)، Until.gone(selector). بدون انتظار مناسب، تصبح الاختبارات غير مستقرة بسبب ظروف السباق — قد لا يظهر العنصر على الشاشة بحلول وقت البحث. يُوصى بتعيين مهلة زمنية لا تقل عن 3–5 ثوانٍ للاستقرار.
الأسئلة الشائعة
UI Automator يعمل على مستوى Accessibility Service ويمكنه التفاعل مع أي تطبيق. يعمل Espresso داخل عملية تطبيق واحد ويستخدم مزامنة تلقائية مع سلسلة واجهة المستخدم. UI Automator أفضل للسيناريوهات عبر التطبيقات، بينما Espresso أفضل للاختبارات المستقرة لتطبيق واحد.
نعم، UI Automator يعمل على جميع الأجهزة التي تعمل بنظام Android API 18+. لا يتطلب وصول جذر — يستخدم Accessibility Service القياسي، الذي يتم تنشيطه عبر Instrumentation عند تشغيل الاختبارات.
يستخدم UI Automator Accessibility Service للحصول على شجرة مكونات واجهة المستخدم الكاملة للشاشة الحالية. ثم يجتاز UiSelector هذه الشجرة ويجد العناصر حسب المعايير المحددة: النص، الصنف، المعرف، وصف المحتوى أو مزيج منها.
نعم، تتيح طريقة UiDevice.takeScreenshot(storePath) أخذ لقطة شاشة للشاشة الحالية وحفظها في ملف. هذا مفيد لتصحيح الأخطاء: عند فشل الاختبار، يمكن حفظ لقطة الشاشة وتحليل حالة الشاشة.
لا يحتوي UI Automator على مزامنة تلقائية، لذلك الاختبارات حساسة للتوقيت. إذا لم يكتمل الرسم المتحرك أو لم يتم عرض العرض بعد، فقد لا يجد findObject العنصر. الحل هو استخدام UiDevice.wait() بمهلة زمنية كافية.
الخلاصة
تغطي مجموعة أدوات UI Automator جميع السيناريوهات الرئيسية للاختبار عبر التطبيقات وهي المعيار لأتمتة Android على مستوى النظام.
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا