UI Automator یک فریمورک از گوگل برای تست خودکار UI اپلیکیشنهای اندروید است که در سطح سیستم کار میکند و میتواند با عناصر رابط کاربری فراتر از یک اپلیکیشن تعامل داشته باشد. برخلاف Espresso، UI Automator به فرآیند یک اپلیکیشن خاص وابسته نیست: میتواند دیالوگهای سیستمی، پنل اعلانها را باز کرده و بین اپلیکیشنها جابهجا شود. به گفته Google Android Developers، UI Automator از Accessibility Service استاندارد برای دسترسی به درخت UI دستگاه استفاده میکند.
نکات کلیدی
UI Automator یک فریمورک برای تست عملکردی UI اندروید است که در سطح سیستمعامل کار میکند. این فریمورک API برای دسترسی به هر عنصر روی صفحه دستگاه، صرفنظر از اینکه متعلق به کدام اپلیکیشن است — از جمله نوار وضعیت سیستم، دیالوگهای مجوزها، صفحه اصلی و اپلیکیشنهای شخص ثالث — ارائه میدهد. این ویژگی آن را برای تست سناریوهایی که فراتر از یک اپلیکیشن هستند، ضروری میکند.
از نظر معماری، UI Automator از Accessibility Service استفاده میکند — همان سرویسی که توسط TalkBack، Switch Access و سایر ابزارهای دسترسپذیری استفاده میشود. از طریق این سرویس، فریمورک درخت کامل کامپوننتهای UI صفحه فعلی را دریافت کرده و امکان اجرای اقداماتی مانند کلیک، سوایپ، وارد کردن متن و فشار طولانی را فراهم میکند.
UI Automator اولین بار در اندروید 4.3 (API 18) ظاهر شد و از آن زمان بخشی از Android Testing Support Library به عنوان ابزار رسمی گوگل برای تست بیناپلیکیشنی است. در AndroidX Test به عنوان یک آرتیفکت جداگانه androidx.test.uiautomator:uiautomator نسخه 2.3.0 (2024) در دسترس است که از تمام نسخههای اندروید از API 18 پشتیبانی میکند.
اصل کار UI Automator بر اساس اسکن درخت Accessibility صفحه فعلی است. هنگام فراخوانی متد findObject(selector)، فریمورک سلسلهمراتب View را پیمایش کرده، اولین عنصر منطبق با شرایط UiSelector را پیدا کرده و یک شی UiObject — پروکسی برای تعامل با View واقعی — برمیگرداند.
یک تست معمولی UI Automator با دریافت نمونه UiDevice شروع میشود که دستگاه فیزیکی را نشان میدهد. UiDevice متدهایی برای جستجوی عناصر، مدیریت فشار دکمهها (Home، Back، Recent)، چرخش صفحه و اسکرینشات فراهم میکند. پس از پیدا شدن عنصر از طریق UiSelector، اقدامات روی UiObject انجام میشود.
در مثال زیر، تست اپلیکیشن Settings را باز کرده، گزینه «باتری» را از طریق متن پیدا کرده و روی آن کلیک میکند. UI Automator نیازی به راهاندازی Activity ندارد — با هر صفحهای از دستگاه، از جمله اپلیکیشنهای شخص ثالث، کار میکند.
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 — کلاس اصلی برای تعامل با دستگاه. این کلاس متدهایی برای جستجوی عناصر، شبیهسازی فشار دکمههای سختافزاری (Home، Back، Menu، Volume)، مدیریت انرژی، اسکرینشات و انتظار برای وضعیتهای خاص صفحه فراهم میکند. UiDevice یک بار در هر تست ایجاد شده و برای تمام عملیات استفاده مجدد میشود.
UiSelector — یک API روان (fluent) برای جستجوی عناصر UI است. برخلاف ViewMatchers در Espresso، UiSelector نیازی به کامپایل ندارد — شرایط جستجو از طریق زنجیرهای از متدها شکل میگیرد: text()، className()، description()، resourceId()، index(). چندین شرط بهطور خودکار از طریق AND منطقی ترکیب میشوند.
| متد UiSelector | کاربرد |
|---|---|
| text(String) | جستجو بر اساس متن دقیق عنصر |
| textContains(String) | جستجو بر اساس قسمتی از متن |
| resourceId(String) | جستجو بر اساس ID منبع (مثلاً com.example:id/button) |
| className(String) | جستجو بر اساس نام کلاس View |
| description(String) | جستجو بر اساس content-description |
| childSelector(selector) | جستجوی عنصر فرزند در یک ظرف |
وقتی چندین عنصر با متن یکسان روی صفحه وجود دارد، UiSelector امکان ترکیب معیارها را میدهد: پیدا کردن ظرف بر اساس ID، سپس داخل آن — عنصر بر اساس متن و کلاس. این کار شناسایی یکتای کامپوننت مورد نیاز را تضمین میکند. متد childSelector محدوده جستجو را تا ظرف مشخص شده محدود میکند که باعث تسریع پیمایش درخت UI میشود.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// داخل لیست عنصر با متن «Wi-Fi» را پیدا کنید
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
Cross-application (تست بیناپلیکیشنی) — اصلیترین قابلیتی است که UI Automator برای آن انتخاب میشود. این فریمورک میتواند بین اپلیکیشنها جابهجا شود، ورود OAuth را از طریق مرورگر تست کند، دیالوگهای سیستمی (مجوزها، انتخاب اپلیکیشن) را بررسی کرده و با نوار وضعیت سیستم، پنل اعلانها و صفحه قفل تعامل داشته باشد.
یک سناریوی معمول تست cross-app: اپلیکیشن مرورگر را برای احراز هویت 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 |
|---|---|---|
| محدوده | کل دستگاه، چندین اپلیکیشن | یک اپلیکیشن |
| همگامسازی | دستی (wait, sleep) | خودکار (Idling Resource) |
| سرعت | کندتر (دسترسی از طریق سرویس) | سریعتر (داخل فرآیند کار میکند) |
| System UI | پشتیبانی میکند (Notifications, Quick Settings) | پشتیبانی نمیکند |
| دقت جستجو | UiSelector بر اساس ویژگیها | ViewMatchers بر اساس نوع و سلسلهمراتب |
| پایداری | کمتر (وابسته به زمانبندی) | بیشتر (انتظار خودکار) |
در عمل، این فریمورکها اغلب با هم استفاده میشوند: Espresso تستهای UI اپلیکیشن اصلی را با پایداری بالا پوشش میدهد و UI Automator برای سناریوهای فراتر از مرزهای اپلیکیشن — ورود OAuth، مجوزهای سیستمی، کار با Share Intent — به کار گرفته میشود. چنین ترکیبی حداکثر پوشش UI را با حداقل هزینه نگهداری تستها فراهم میکند.
اتصال 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 thread-safe نیست — تمام عملیات باید در یک رشته از متد تست انجام شوند. ایجاد 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 استفاده میکند. UI Automator برای سناریوهای بیناپلیکیشنی بهتر است، Espresso — برای تستهای پایدار یک اپلیکیشن.
بله، UI Automator روی تمام دستگاههای با Android API 18+ کار میکند. نیازی به دسترسی root ندارد — از Accessibility Service استاندارد استفاده میشود که از طریق Instrumentation هنگام اجرای تستها فعال میشود.
UI Automator از Accessibility Service برای دریافت درخت کامل کامپوننتهای UI صفحه فعلی استفاده میکند. سپس UiSelector این درخت را پیمایش کرده و عناصر را بر اساس معیارهای داده شده پیدا میکند: متن، کلاس، ID، content-description یا ترکیبی از آنها.
بله، متد UiDevice.takeScreenshot(storePath) امکان گرفتن اسکرینشات از صفحه فعلی و ذخیره آن در فایل را فراهم میکند. این برای اشکالزدایی مفید است: در صورت شکست تست، میتوان اسکرینشات را ذخیره و وضعیت صفحه را تحلیل کرد.
UI Automator همگامسازی خودکار ندارد، بنابراین تستها به زمانبندی حساس هستند. اگر انیمیشن کامل نشده یا View فرصت رندر شدن نداشته باشد، findObject ممکن است عنصر را پیدا نکند. راهحل — استفاده از UiDevice.wait() با timeout کافی.
خلاصه
مجموعه ابزارهای UI Automator تمام سناریوهای کلیدی تست بیناپلیکیشنی را پوشش میدهد و استانداردی برای خودکارسازی اندروید در سطح سیستم است.
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید