UI Automator টেস্টিং ফ্রেমওয়ার্ক, UI টেস্ট তৈরি করার জন্য API-এর একটি সেট প্রদান করে যা ব্যবহারকারীর অ্যাপ ও সিস্টেম অ্যাপের সাথে ইন্টার্যাক্ট করে।
আধুনিক UI Automator টেস্টিংয়ের ভূমিকা
UI Automator 2.4-এ স্ট্রিমলাইন করা, Kotlin-এর সাথে মানানসই ডোমেন স্পেসিফিক ল্যাঙ্গুয়েজ (DSL) চালু করা হয়েছে যা Android-এর জন্য UI টেস্ট লেখার কাজ সহজ করে দেয়। এই নতুন API সারফেস প্রেডিকেট-ভিত্তিক এলিমেন্ট খোঁজা এবং অ্যাপের অবস্থার উপর স্পষ্ট নিয়ন্ত্রণের উপর ফোকাস করে। আরও সহজে ম্যানেজ করা যায় এবং নির্ভরযোগ্য এমন অটোমেটেড টেস্ট তৈরি করতে এটি ব্যবহার করুন।
UI Automator আপনাকে অ্যাপের প্রসেসের বাইরে থেকে অ্যাপ পরীক্ষা করতে দেয়। এটি আপনাকে ছোট করা প্রয়োগ করে রিলিজ ভার্সন টেস্ট করতে দেয়। এছাড়াও, UI Automator ম্যাক্রোবেঞ্চমার্ক টেস্ট লেখার সময় সাহায্য করে।
আধুনিক পদ্ধতির মূল ফিচারের মধ্যে এগুলি অন্তর্ভুক্ত:
- আরও পরিচ্ছন্ন ও অর্থপূর্ণ টেস্ট কোডের জন্য একটি নির্দিষ্ট
uiAutomatorটেস্ট স্কোপ। - স্পষ্ট প্রেডিকেট সহ UI এলিমেন্ট খোঁজার জন্য
onElement,onElementsএবংonElementOrNull-এর মতো পদ্ধতি। - শর্তসাপেক্ষ এলিমেন্ট
onElement*(timeoutMs: Long = 10000)-এর জন্য বিল্ট-ইন ওয়েটিং মেকানিজম waitForStableএবংwaitForAppToBeVisible-এর মতো এক্সপ্লিসিট অ্যাপ স্টেট ম্যানেজমেন্ট।- মাল্টি-উইন্ডো টেস্টিং সিনারিওর জন্য অ্যাক্সেসিবিলিটি উইন্ডো নোডের সাথে সরাসরি ইন্টার্যাকশন।
- বিল্ট-ইন স্ক্রিনশট নেওয়ার ক্ষমতা এবং ভিজ্যুয়াল টেস্টিং ও ডিবাগিংয়ের জন্য
ResultsReporter।
আপনার প্রোজেক্ট সেট-আপ করুন
আধুনিক UI Automator API ব্যবহার করা শুরু করতে, আপনার প্রোজেক্টের
build.gradle.kts ফাইল আপডেট করুন যাতে লেটেস্ট ডিপেন্ডেন্সি অন্তর্ভুক্ত থাকে:
Kotlin
dependencies {
...
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.4.0-alpha05")
}
গ্ৰুভি
dependencies {
...
androidTestImplementation "androidx.test.uiautomator:uiautomator:2.4.0-alpha05"
}
API-এর মূল ধারণা
নিম্নলিখিত বিভাগগুলি আধুনিক UI Automator API-এর মূল ধারণাগুলি বর্ণনা করে।
uiAutomator টেস্ট স্কোপ
uiAutomator { ... }
ব্লকের মধ্যে সব নতুন UI Automator API অ্যাক্সেস করুন। এই ফাংশনটি একটি UiAutomatorTestScope তৈরি করে যা আপনার টেস্ট অপারেশনের জন্য একটি সংক্ষিপ্ত
এবং টাইপ-নিরাপদ পরিবেশ প্রদান করে।
uiAutomator {
// All your UI Automator actions go here
startApp("com.example.targetapp")
onElement { textAsString() == "Hello, World!" }.click()
}
UI এলিমেন্ট খুঁজুন
UI এলিমেন্ট লোকেট করতে প্রেডিকেট সহ UI Automator API ব্যবহার করুন। এইসব প্রেডিকেট আপনাকে টেক্সট, বেছে নেওয়া বা ফোকাসড স্টেট এবং কন্টেন্টের বিবরণের মতো প্রপার্টির জন্য শর্ত নির্ধারণ করতে দেয়।
onElement { predicate }: ডিফল্ট টাইমআউটের মধ্যে প্রেডিকেটের সাথে মেলে এমন প্রথম UI এলিমেন্ট ফিরিয়ে দেয়। ফাংশনটি একটি ব্যতিক্রম থ্রো করে যদি এটি একটি ম্যাচিং এলিমেন্ট খুঁজে না পায়।// Find a button with the text "Submit" and click it onElement { textAsString() == "Submit" }.click() // Find a UI element by its resource ID onElement { viewIdResourceName == "my_button_id" }.click() // Allow a permission request watchFor(PermissionDialog) { clickAllow() }onElementOrNull { predicate }:onElement-এর মতো, তবে টাইমআউটের মধ্যে ফাংশনটি কোনও ম্যাচিং এলিমেন্ট খুঁজে না পেলেnullরিটার্ন করে। এটি কোনও ব্যতিক্রম দেখায় না। ঐচ্ছিক এলিমেন্টের জন্য এই পদ্ধতি ব্যবহার করুন।val optionalButton = onElementOrNull { textAsString() == "Skip" } optionalButton?.click() // Click only if the button existsonElements { predicate }: প্রদত্ত প্রেডিকেটের সাথে অন্তত একটি UI এলিমেন্ট না মেলা পর্যন্ত অপেক্ষা করে, তারপর সবকটি মিলে যাওয়া UI এলিমেন্টের একটি তালিকা দেখায়।// Get all items in a list Ui element val listItems = onElements { className == "android.widget.TextView" && isClickable } listItems.forEach { it.click() }
onElement কল ব্যবহার করার জন্য এখানে কিছু পরামর্শ দেওয়া হল:
নেস্টেড এলিমেন্টের জন্য
onElementকল চেইন করা: আপনি পেরেন্ট-চাইল্ড হায়ারার্কি অনুসরণ করে অন্যান্য এলিমেন্টের মধ্যে এলিমেন্ট খুঁজে পেতেonElementকল চেইন করতে পারেন।// Find a parent Ui element with ID "first", then its child with ID "second", // then its grandchild with ID "third", and click it. onElement { viewIdResourceName == "first" } .onElement { viewIdResourceName == "second" } .onElement { viewIdResourceName == "third" } .click()মিলিসেকেন্ডের প্রতিনিধিত্বকারী একটি মান পাস করে
onElement*ফাংশনের জন্য একটি টাইমআউট নির্দিষ্ট করুন।// Find a Ui element with a zero timeout (instant check) onElement(0) { viewIdResourceName == "something" }.click() // Find a Ui element with a custom timeout of 10 seconds onElement(10_000) { textAsString() == "Long loading text" }.click()
UI এলিমেন্টের সাথে ইন্টার্যাক্ট করা
ক্লিক সিমুলেট করে বা এডিট করা যায় এমন ফিল্ডে টেক্সট সেট করে UI এলিমেন্টের সাথে ইন্টার্যাক্ট করুন।
// Click a Ui element
onElement { textAsString() == "Tap Me" }.click()
// Set text in an editable field
onElement { className == "android.widget.EditText" }.setText("My input text")
// Perform a long click
onElement { contentDescription == "Context Menu" }.longClick()
অ্যাপের স্ট্যাটাস ও ওয়াচার ম্যানেজ করুন
আপনার অ্যাপের লাইফসাইকেল ম্যানেজ করুন এবং আপনার টেস্টের সময় দেখা যেতে পারে এমন অপ্রত্যাশিত UI এলিমেন্ট ম্যানেজ করুন।
অ্যাপ লাইফসাইকেল ম্যানেজমেন্ট
API-গুলি টেস্টের অধীনে অ্যাপের অবস্থা নিয়ন্ত্রণ করার উপায় প্রদান করে:
// Start a specific app by package name. Used for benchmarking and other
// self-instrumenting tests.
startApp("com.example.targetapp")
// Start a specific activity within the target app
startActivity(SomeActivity::class.java)
// Start an intent
startIntent(myIntent)
// Clear the app's data (resets it to a fresh state)
clearAppData("com.example.targetapp")
অপ্রত্যাশিত UI ম্যানেজ করা
watchFor API আপনাকে অপ্রত্যাশিত UI এলিমেন্টের জন্য হ্যান্ডলার সংজ্ঞায়িত করতে দেয়,
যেমন অনুমতি ডায়ালগ, যা আপনার টেস্ট ফ্লো চলাকালীন দেখা যেতে পারে। এটি
ইন্টার্নাল ওয়াচার মেকানিজম ব্যবহার করে তবে আরও বেশি নমনীয়তা অফার করে।
import androidx.test.uiautomator.PermissionDialog
@Test
fun myTestWithPermissionHandling() = uiAutomator {
startActivity(MainActivity::class.java)
// Register a watcher to click "Allow" if a permission dialog appears
watchFor(PermissionDialog) { clickAllow() }
// Your test steps that might trigger a permission dialog
onElement { textAsString() == "Request Permissions" }.click()
// Example: You can register a different watcher later if needed
clearAppData("com.example.targetapp")
// Now deny permissions
startApp("com.example.targetapp")
watchFor(PermissionDialog) { clickDeny() }
onElement { textAsString() == "Request Permissions" }.click()
}
PermissionDialog হল ScopedWatcher<T>-এর একটি উদাহরণ, যেখানে T হল
watchFor-এ ব্লকের স্কোপ হিসেবে পাস করা অবজেক্ট। আপনি এই প্যাটার্নের উপর ভিত্তি করে কাস্টম
ওয়াচার তৈরি করতে পারবেন।
অ্যাপের দৃশ্যমানতা ও স্টেবিলিটির জন্য অপেক্ষা করুন
কখনও কখনও এলিমেন্ট দৃশ্যমান বা স্থিতিশীল হওয়ার জন্য টেস্টকে অপেক্ষা করতে হয়। UI Automator এই বিষয়ে সাহায্য করার জন্য একাধিক API অফার করে।
waitForAppToBeVisible("com.example.targetapp") কাস্টমাইজ করা যায় এমন টাইমআউটের মধ্যে স্ক্রিনে
প্রদত্ত প্যাকেজের নাম সহ UI এলিমেন্ট দেখানোর জন্য অপেক্ষা করে।
// Wait for the app to be visible after launching it
startApp("com.example.targetapp")
waitForAppToBeVisible("com.example.targetapp")
অ্যাপের UI-এর সাথে ইন্টার্যাক্ট করার আগে সেটি স্টেবল কিনা তা যাচাই করতে waitForStable() API ব্যবহার করুন।
// Wait for the entire active window to become stable
activeWindow().waitForStable()
// Wait for a specific Ui element to become stable (e.g., after a loading animation)
onElement { viewIdResourceName == "my_loading_indicator" }.waitForStable()
ম্যাক্রোবেঞ্চমার্ক ও বেসলাইন প্রোফাইলের জন্য UI Automator ব্যবহার করা
Jetpack Macrobenchmark-এর মাধ্যমে পারফর্ম্যান্স টেস্টিং এবং বেসলাইন প্রোফাইল তৈরি করার জন্য UI Automator ব্যবহার করুন, কারণ এটি আপনার অ্যাপের সাথে ইন্টার্যাক্ট করার এবং ব্যবহারকারীর দৃষ্টিকোণ থেকে পারফর্ম্যান্স পরিমাপ করার একটি নির্ভরযোগ্য উপায় প্রদান করে।
Macrobenchmark, UI অটোমেটর API ব্যবহার করে UI পরিচালনা করে এবং ইন্টার্যাকশন পরিমাপ করে।
যেমন, স্টার্টআপ বেঞ্চমার্কে, UI কন্টেন্ট কখন সম্পূর্ণ লোড হয়েছে তা শনাক্ত করতে আপনি onElement ব্যবহার করতে পারেন, যা আপনাকে সম্পূর্ণ ডিসপ্লে হতে সময় (TTFD) পরিমাপ করতে সাহায্য করে। জ্যাঙ্ক বেঞ্চমার্কে, ফ্রেম টাইমিং পরিমাপ করার জন্য UI Automator API ব্যবহার করে তালিকা স্ক্রল করা হয় বা
অ্যানিমেশন চালানো হয়। পরিমাপ শুরু করার আগে অ্যাপকে সঠিক অবস্থায় নিয়ে আসার জন্য startActivity() বা
startIntent()-এর মতো ফাংশন উপযোগী।
বেসলাইন প্রোফাইল তৈরি করার সময়, কোন ক্লাস ও পদ্ধতির জন্য প্রি-কম্পাইলেশন প্রয়োজন তা রেকর্ড করতে, আপনি অ্যাপের ক্রিটিকাল ইউজার
জার্নি (CUJ) অটোমেট করেন। UI
Automator হল এই অটোমেশন স্ক্রিপ্ট লেখার জন্য একটি আদর্শ টুল। আধুনিক
DSL-এর প্রেডিকেট-ভিত্তিক এলিমেন্ট খোঁজা এবং বিল্ট-ইন অপেক্ষা করার মেকানিজম (onElement)
অন্যান্য পদ্ধতির তুলনায় আরও শক্তিশালী এবং নির্ধারক টেস্ট এক্সিকিউশনের দিকে পরিচালিত করে।
এই স্থিতিশীলতা ফ্লেকিনেস কমায় এবং নিশ্চিত করে যে জেনারেট করা বেসলাইন প্রোফাইল
আপনার সবচেয়ে গুরুত্বপূর্ণ ব্যবহারকারীর ফ্লো চলাকালীন এক্সিকিউট করা কোড পাথগুলি
সঠিকভাবে প্রতিফলিত করে।
উন্নত ফিচার
আরও জটিল টেস্টিংয়ের ক্ষেত্রে নিম্নলিখিত ফিচারগুলি উপযোগী।
একাধিক উইন্ডোর সাথে ইন্টার্যাক্ট করুন
UI Automator API আপনাকে সরাসরি UI এলিমেন্টের সাথে ইন্টার্যাক্ট ও তা পরীক্ষা করতে দেয়। এটি বিশেষ করে একাধিক উইন্ডো সহ পরিস্থিতির জন্য উপযোগী, যেমন পিকচার-ইন-পিকচার (PiP) মোড বা স্প্লিট-স্ক্রিন লেআউট।
// Find the first window that is in Picture-in-Picture mode
val pipWindow = windows()
.first { it.isInPictureInPictureMode == true }
// Now you can interact with elements within that specific window
pipWindow.onElement { textAsString() == "Play" }.click()
স্ক্রিনশট ও ভিজ্যুয়াল অ্যাসার্শন
আপনার টেস্টের মধ্যে সরাসরি সম্পূর্ণ স্ক্রিন, নির্দিষ্ট উইন্ডো বা আলাদা আলাদা UI এলিমেন্টের স্ক্রিনশট ক্যাপচার করুন। এটি ভিজ্যুয়াল রিগ্রেশন টেস্টিং ও ডিবাগিংয়ের ক্ষেত্রে সহায়ক।
uiautomator {
// Take a screenshot of the entire active window
val fullScreenBitmap: Bitmap = activeWindow().takeScreenshot()
fullScreenBitmap.saveToFile(File("/sdcard/Download/full_screen.png"))
// Take a screenshot of a specific UI element (e.g., a button)
val buttonBitmap: Bitmap = onElement { viewIdResourceName == "my_button" }.takeScreenshot()
buttonBitmap.saveToFile(File("/sdcard/Download/my_button_screenshot.png"))
// Example: Take a screenshot of a PiP window
val pipWindowScreenshot = windows()
.first { it.isInPictureInPictureMode == true }
.takeScreenshot()
pipWindowScreenshot.saveToFile(File("/sdcard/Download/pip_screenshot.png"))
}
Bitmap-এর জন্য saveToFile এক্সটেনশন ফাংশন ক্যাপচার করা ছবি নির্দিষ্ট পাথে সেভ করার
প্রক্রিয়াকে সহজ করে তোলে।
ডিবাগিংয়ের জন্য ResultsReporter ব্যবহার করুন
ResultsReporter আপনাকে স্ক্রিনশটের মতো টেস্ট আর্টিফ্যাক্ট সরাসরি Android Studio-তে টেস্ট ফলাফলের সাথে
যুক্ত করতে সাহায্য করে, যাতে আপনি সহজেই সেগুলি পরীক্ষা ও
ডিবাগ করতে পারেন।
uiAutomator {
startApp("com.example.targetapp")
val reporter = ResultsReporter("MyTestArtifacts") // Name for this set of results
val file = reporter.addNewFile(
filename = "my_screenshot",
title = "Accessible button image" // Title that appears in Android Studio test results
)
// Take a screenshot of an element and save it using the reporter
onElement { textAsString() == "Accessible button" }
.takeScreenshot()
.saveToFile(file)
// Report the artifacts to instrumentation, making them visible in Android Studio
reporter.reportToInstrumentation()
}
UI Automator-এর পুরনো ভার্সন থেকে মাইগ্রেট করা
আপনার কাছে যদি পুরনো API সারফেস দিয়ে লেখা UI Automator টেস্ট থাকে, তাহলে আধুনিক পদ্ধতিতে মাইগ্রেট করার জন্য রেফারেন্স হিসেবে নিম্নলিখিত টেবিলটি ব্যবহার করুন:
| অ্যাকশনের ধরন | পুরনো UI অটোমেটর পদ্ধতি | নতুন UI অটোমেটর পদ্ধতি |
|---|---|---|
| এন্ট্রি পয়েন্ট | UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) |
uiAutomator { ... } স্কোপে টেস্ট লজিক র্যাপ করুন। |
| UI এলিমেন্ট খুঁজুন | device.findObject(By.res("com.example.app:id/my_button")) |
onElement { viewIdResourceName == "my\_button" } |
| UI এলিমেন্ট খুঁজুন | device.findObject(By.text("Click Me")) |
onElement { textAsString() == "Click Me" } |
| অ্যাক্টিভ নয় এমন UI-এর জন্য অপেক্ষা করুন | device.waitForIdle() |
onElement-এর বিল্ট-ইন টাইমআউট মেকানিজমকে অগ্রাধিকার দিন; অন্যথায়, activeWindow().waitForStable() |
| চাইল্ড এলিমেন্ট খুঁজুন | ম্যানুয়ালি নেস্ট করা findObjectটি কল |
onElement().onElement() চেইনিং |
| অনুমতি সংক্রান্ত ডায়ালগ ম্যানেজ করুন | UiAutomator.registerWatcher() |
watchFor(PermissionDialog) |