यूज़र इंटरफ़ेस (यूआई) ऑटोमेशन की मदद से, अपने-आप होने वाले टेस्ट में बदलाव करने की सुविधा

यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर टेस्टिंग फ़्रेमवर्क, यूज़र इंटरफ़ेस (यूआई) टेस्ट बनाने के लिए एपीआई का एक सेट उपलब्ध कराता है. ये टेस्ट, उपयोगकर्ता के ऐप्लिकेशन और सिस्टम ऐप्लिकेशन के साथ इंटरैक्ट करते हैं.

यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर की आधुनिक टेस्टिंग के बारे में जानकारी

यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर 2.4 में, Kotlin के साथ काम करने वाली, डोमेन के लिए खास भाषा (डीएसएल) लॉन्च की गई है. इससे Android के लिए यूज़र इंटरफ़ेस (यूआई) टेस्ट लिखना आसान हो जाता है. इस नए एपीआई में, प्रेडिकेट के आधार पर एलिमेंट ढूंढने और ऐप्लिकेशन के स्टेटस पर साफ़ तौर पर कंट्रोल करने की सुविधा मिलती है. इसका इस्तेमाल करके, ऑटोमेटेड टेस्ट बनाएं जिन्हें आसानी से मैनेज किया जा सके और जो भरोसेमंद हों.

यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर की मदद से, ऐप्लिकेशन की प्रोसेस के बाहर से भी उसकी टेस्टिंग की जा सकती है. इससे, रिलीज़ किए जाने वाले वर्शन की टेस्टिंग, मिनीफ़िकेशन लागू करके की जा सकती है. यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर, मैक्रोबेंचमार्क टेस्ट लिखने में भी मदद करता है.

आधुनिक तरीके की मुख्य सुविधाएं:

  • साफ़ और ज़्यादा जानकारी देने वाला टेस्ट कोड लिखने के लिए, uiAutomator टेस्ट स्कोप की सुविधा.
  • साफ़ तौर पर प्रेडिकेट वाले यूज़र इंटरफ़ेस (यूआई) एलिमेंट ढूंढने के लिए, onElement, onElements, और onElementOrNull जैसे तरीके.
  • शर्तों के हिसाब से काम करने वाले एलिमेंट के लिए, बिल्ट-इन वेटिंग मैकेनिज़्म onElement*(timeoutMs: Long = 10000)
  • ऐप्लिकेशन के स्टेटस को साफ़ तौर पर मैनेज करने की सुविधा. जैसे, waitForStable और waitForAppToBeVisible.
  • मल्टी-विंडो टेस्टिंग के लिए, सुलभता विंडो नोड के साथ सीधे इंटरैक्शन की सुविधा.
  • विज़ुअल टेस्टिंग और डीबग करने के लिए, बिल्ट-इन स्क्रीनशॉट की सुविधाएं और ResultsReporter.

अपना प्रोजेक्ट सेट अप करना

यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के नए एपीआई का इस्तेमाल शुरू करने के लिए, अपने प्रोजेक्ट की build.gradle.kts फ़ाइल को अपडेट करें, ताकि इसमें सबसे नई डिपेंडेंसी शामिल हो:

Kotlin

dependencies {
  ...
  androidTestImplementation("androidx.test.uiautomator:uiautomator:2.4.0-alpha05")
}

शानदार

dependencies {
  ...
  androidTestImplementation "androidx.test.uiautomator:uiautomator:2.4.0-alpha05"
}

एपीआई के मुख्य सिद्धांत

यहां दिए गए सेक्शन में, यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के नए एपीआई के मुख्य सिद्धांतों के बारे में बताया गया है.

uiAutomator टेस्ट स्कोप

uiAutomator { ... } ब्लॉक में, यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के सभी नए एपीआई ऐक्सेस करें. इस फ़ंक्शन से UiAutomatorTestScope बनता है. यह आपके टेस्ट ऑपरेशन के लिए, सटीक और टाइप-सेफ़ एनवायरमेंट उपलब्ध कराता है.

uiAutomator {
  // All your UI Automator actions go here
  startApp("com.example.targetapp")
  onElement { textAsString() == "Hello, World!" }.click()
}

यूज़र इंटरफ़ेस (यूआई) एलिमेंट ढूंढना

यूज़र इंटरफ़ेस (यूआई) एलिमेंट ढूंढने के लिए, प्रेडिकेट के साथ यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के एपीआई का इस्तेमाल करें. इन प्रेडिकेट की मदद से, प्रॉपर्टी के लिए शर्तें तय की जा सकती हैं. जैसे, टेक्स्ट, चुना गया या फ़ोकस किया गया स्टेटस, और कॉन्टेंट का ब्यौरा.

  • onElement { predicate }: डिफ़ॉल्ट टाइम आउट में, प्रेडिकेट से मेल खाने वाला पहला यूज़र इंटरफ़ेस (यूआई) एलिमेंट दिखाता है. अगर फ़ंक्शन को मेल खाने वाला कोई एलिमेंट नहीं मिलता है, तो वह एक अपवाद दिखाता है.

    // 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 exists
    
  • onElements { predicate }: तब तक इंतज़ार करता है, जब तक कम से कम एक यूज़र इंटरफ़ेस (यूआई) एलिमेंट, दिए गए प्रेडिकेट से मेल न खा जाए. इसके बाद, मेल खाने वाले सभी यूज़र इंटरफ़ेस (यूआई) एलिमेंट की सूची दिखाता है.

    // Get all items in a list Ui element
    val listItems = onElements { className == "android.widget.TextView" && isClickable }
    listItems.forEach { it.click() }
    

onElement कॉल का इस्तेमाल करने के लिए यहां कुछ सलाह दी गई हैं:

  • नेस्ट किए गए एलिमेंट के लिए, onElement कॉल को चेन करना: अन्य एलिमेंट में मौजूद एलिमेंट ढूंढने के लिए, onElement कॉल को चेन किया जा सकता है. इसके लिए, पैरंट-चाइल्ड hierarchy का इस्तेमाल किया जाता है.

    // 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()
    

यूज़र इंटरफ़ेस (यूआई) एलिमेंट के साथ इंटरैक्ट करना

यूज़र इंटरफ़ेस (यूआई) एलिमेंट के साथ इंटरैक्ट करने के लिए, क्लिक सिम्युलेट करें या बदलाव किए जा सकने वाले फ़ील्ड में टेक्स्ट सेट करें.

// 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()

ऐप्लिकेशन के स्टेटस और वॉचर मैनेज करना

अपने ऐप्लिकेशन के लाइफ़साइकल को मैनेज करें और टेस्ट के दौरान दिखने वाले अनचाहे यूज़र इंटरफ़ेस (यूआई) एलिमेंट को हैंडल करें.

ऐप्लिकेशन के लाइफ़साइकल को मैनेज करना

एपीआई की मदद से, टेस्ट किए जा रहे ऐप्लिकेशन के स्टेटस को कंट्रोल किया जा सकता है:

// 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")

अनचाहे यूज़र इंटरफ़ेस (यूआई) को हैंडल करना

watchFor एपीआई की मदद से, अनचाहे यूज़र इंटरफ़ेस (यूआई) एलिमेंट के लिए हैंडलर तय किए जा सकते हैं. जैसे, अनुमति वाले डायलॉग. ये एलिमेंट, टेस्ट फ़्लो के दौरान दिख सकते हैं. यह इंटरनल वॉचर मैकेनिज़्म का इस्तेमाल करता है, लेकिन इसमें ज़्यादा विकल्प मिलते हैं.

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 में ब्लॉक के लिए स्कोप के तौर पर पास किया जाता है. इस पैटर्न के आधार पर, कस्टम वॉचर बनाए जा सकते हैं.

ऐप्लिकेशन के दिखने और स्थिर होने का इंतज़ार करना

कभी-कभी टेस्ट के दौरान, एलिमेंट के दिखने या स्थिर होने का इंतज़ार करना पड़ता है. यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर, इसमें मदद करने के लिए कई एपीआई उपलब्ध कराता है.

waitForAppToBeVisible("com.example.targetapp") एपीआई, दिए गए पैकेज के नाम वाले यूज़र इंटरफ़ेस (यूआई) एलिमेंट के स्क्रीन पर दिखने का इंतज़ार करता है. इसके लिए, टाइम आउट को पसंद के मुताबिक सेट किया जा सकता है.

// Wait for the app to be visible after launching it
startApp("com.example.targetapp")
waitForAppToBeVisible("com.example.targetapp")

waitForStable() एपीआई का इस्तेमाल करके, यह पुष्टि करें कि ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) को स्थिर माना जाता है या नहीं. इसके बाद ही, उससे इंटरैक्ट करें.

// 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()

मैक्रोबेंचमार्क और बेसलाइन प्रोफ़ाइल के लिए, यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर का इस्तेमाल करना

Jetpack Macrobenchmark की मदद से परफ़ॉर्मेंस टेस्टिंग और बेसलाइन प्रोफ़ाइल जनरेट करने के लिए, यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर का इस्तेमाल करें. इसकी वजह यह है कि यह आपके ऐप्लिकेशन के साथ इंटरैक्ट करने और एंड-यूज़र के नज़रिए से परफ़ॉर्मेंस को मेज़र करने का भरोसेमंद तरीका है.

मैक्रोबेंचमार्क, यूज़र इंटरफ़ेस (यूआई) को चलाने और इंटरैक्शन को मेज़र करने के लिए, यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के एपीआई का इस्तेमाल करता है. उदाहरण के लिए, स्टार्टअप बेंचमार्क में, onElement का इस्तेमाल करके यह पता लगाया जा सकता है कि यूज़र इंटरफ़ेस (यूआई) का कॉन्टेंट कब पूरी तरह से लोड हो गया है. इससे, Time to Full Display (TTFD) को मेज़र किया जा सकता है. जंक बेंचमार्क में, फ़्रेम टाइमिंग को मेज़र करने के लिए, यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के एपीआई का इस्तेमाल करके, सूचियों को स्क्रोल किया जाता है या ऐनिमेशन चलाए जाते हैं. startActivity() या startIntent() जैसे फ़ंक्शन, मेज़रमेंट शुरू होने से पहले ऐप्लिकेशन को सही स्टेटस में लाने के लिए काम के होते हैं.

बेसलाइन प्रोफ़ाइल जनरेट करते समय, अपने ऐप्लिकेशन के अहम उपयोगकर्ता के सफ़र (सीयूजे) को ऑटोमेट करें. इससे यह रिकॉर्ड किया जा सकेगा कि किन क्लास और तरीकों के लिए, पहले से कंपाइल करने की ज़रूरत है. इन ऑटोमेशन स्क्रिप्ट को लिखने के लिए, यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर एक बेहतरीन टूल है. डीएसएल के नए वर्शन में, प्रेडिकेट के आधार पर एलिमेंट ढूंढने और बिल्ट-इन वेट मैकेनिज़्म (onElement) की सुविधा मिलती है. इससे, अन्य तरीकों की तुलना में टेस्ट ज़्यादा मज़बूत और सटीक तरीके से किए जा सकते हैं. इस स्थिरता से, फ़्लेकीनेस कम होती है. साथ ही, यह पक्का होता है कि जनरेट की गई बेसलाइन प्रोफ़ाइल, आपके सबसे अहम उपयोगकर्ता फ़्लो के दौरान एक्ज़ीक्यूट किए गए कोड पाथ को सटीक तरीके से दिखाए.

बेहतर सुविधाएं

ज़्यादा मुश्किल टेस्टिंग के लिए, ये सुविधाएं काम की हैं.

एक से ज़्यादा विंडो के साथ इंटरैक्ट करना

यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के एपीआई की मदद से, यूज़र इंटरफ़ेस (यूआई) एलिमेंट के साथ सीधे इंटरैक्ट किया जा सकता है और उनकी जांच की जा सकती है. यह उन मामलों के लिए खास तौर पर काम का है जिनमें एक से ज़्यादा विंडो शामिल होती हैं. जैसे, पिक्चर-इन-पिक्चर (पीआईपी) मोड या स्प्लिट-स्क्रीन लेआउट.

// 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()

स्क्रीनशॉट और विज़ुअल असर्शन

अपने टेस्ट में सीधे तौर पर, पूरी स्क्रीन, चुनिंदा विंडो या अलग-अलग यूज़र इंटरफ़ेस (यूआई) एलिमेंट के स्क्रीनशॉट कैप्चर करें. यह विज़ुअल रिग्रेशन टेस्टिंग और डीबग करने के लिए काम का है.

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

यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के पुराने वर्शन से माइग्रेट करना

अगर आपके पास यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर के पुराने एपीआई का इस्तेमाल करके लिखे गए टेस्ट मौजूद हैं, तो आधुनिक तरीके से माइग्रेट करने के लिए, यहां दी गई टेबल को रेफ़रंस के तौर पर इस्तेमाल करें:

कार्रवाई प्रकार यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर का पुराना तरीका यूज़र इंटरफ़ेस (यूआई) ऑटोमेटर का नया तरीका
एंट्री पॉइंट UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) टेस्ट लॉजिक को uiAutomator { ... } स्कोप में रैप करें.
यूज़र इंटरफ़ेस (यूआई) एलिमेंट ढूंढना device.findObject(By.res("com.example.app:id/my_button")) onElement { viewIdResourceName == "my\_button" }
यूज़र इंटरफ़ेस (यूआई) एलिमेंट ढूंढना device.findObject(By.text("Click Me")) onElement { textAsString() == "Click Me" }
आइडल यूज़र इंटरफ़ेस (यूआई) का इंतज़ार करना device.waitForIdle() onElement के बिल्ट-इन टाइम आउट मैकेनिज़्म को प्राथमिकता दें. इसके अलावा, activeWindow().waitForStable() का इस्तेमाल करें
चाइल्ड एलिमेंट ढूंढना findObject कॉल को मैन्युअल तरीके से नेस्ट करना onElement().onElement() को चेन करना
अनुमति वाले डायलॉग को हैंडल करना UiAutomator.registerWatcher() watchFor(PermissionDialog)