ইন্টারঅপারেবিলিটি

Compose সাধারণ টেস্টিং ফ্রেমওয়ার্কের সাথে ইন্টিগ্রেট করে।

Espresso-র সাথে ইন্টারঅপারেবিলিটি

হাইব্রিড অ্যাপে, আপনি ভিউ হায়ারার্কির মধ্যে কম্পোজ কম্পোনেন্ট এবং কম্পোজ কম্পোজেবলের মধ্যে ভিউ খুঁজে পেতে পারেন (AndroidView কম্পোজেবলের মাধ্যমে)।

কোনও ধরনের ম্যাচ করার জন্য বিশেষ কোনও ধাপের প্রয়োজন নেই। আপনি Espresso-এর onView-এর সাথে ভিউ এবং ComposeTestRule-এর সাথে কম্পোজ এলিমেন্ট ম্যাচ করেন।

@Test
fun androidViewInteropTest() {
    // Check the initial state of a TextView that depends on a Compose state.
    Espresso.onView(withText("Hello Views")).check(matches(isDisplayed()))
    // Click on the Compose button that changes the state.
    composeTestRule.onNodeWithText("Click here").performClick()
    // Check the new value.
    Espresso.onView(withText("Hello Compose")).check(matches(isDisplayed()))
}

Compose ইন্টারঅপারেবিলিটি টেস্টিংয়ের জন্য View-স্কোপড সিম্যান্টিক্স যোগ করা

নির্দিষ্ট ভিউতে কম্পোজ সার্চের স্কোপ

Compose-এ জটিল UI মাইগ্রেট করার সময়, আপনি একাধিক ট্র্যাডিশনাল Android View-এর মধ্যে নেস্ট করা একই ধরনের Compose এলিমেন্ট দেখতে পেতে পারেন—যেমন, RecyclerView বা ViewPager-এর মধ্যে। এইসব পরিস্থিতিতে, onNodeWithText("Save")-এর মতো স্ট্যান্ডার্ড কম্পোজ সার্চ "একাধিক নোড পাওয়া গেছে" সমস্যার কারণে ব্যর্থ হতে পারে।

এইসব এলিমেন্ট আলাদা করতে ডাইনামিক টেস্ট ট্যাগ ইনজেক্ট করার জন্য আপনার প্রোডাকশন কোড পরিবর্তন করার পরিবর্তে, আপনি সরাসরি নির্দিষ্ট Android ভিউতে আপনার Compose টেস্ট স্কোপ করতে পারেন।

আপনার টেস্ট নিয়মে onRootWithViewInteraction API ব্যবহার করুন। এই ফাংশনটি Espresso ViewInteraction গ্রহণ করে, যা আপনাকে Espresso ব্যবহার করে একটি নির্দিষ্ট কন্টেনার ভিউ আলাদা করতে এবং সেই স্কোপড হায়ারার্কির মধ্যে একচেটিয়াভাবে কম্পোজ ইন্টারঅ্যাকশন করতে দেয়।

তালিকার আইটেমের সাথে ইন্টার‍্যাক্ট করা

নির্দিষ্ট RecyclerView সারির মধ্যে কোনও কম্পোজ এলিমেন্টের সাথে ইন্টার‍্যাক্ট করতে হলে, সারিটি খুঁজে পেতে Espresso ব্যবহার করুন, তারপর আপনার কম্পোজ ইন্টার‍্যাকশনকে সেটির মধ্যে সীমাবদ্ধ করুন। এটি অন্য সব সারিতে একই ধরনের কম্পোজ এলিমেন্টকে উপেক্ষা করে।

@Test
fun testComposeButtonInsideRecyclerViewItem() = runComposeUiTest {
    // Scroll to the desired position using Espresso
    Espresso.onView(withId(recyclerViewId))
        .perform(RecyclerViewActions.scrollToPosition<MyViewHolder>(3))

    // Define an Espresso ViewInteraction that uniquely identifies the row
    val rowView = Espresso.onView(
        allOf(
            withId(rootViewId),
            hasDescendant(withText("Item #3"))
        )
    )

    // Scope the Compose search strictly to that specific row View
    onRootWithViewInteraction(rowView)
        .onNode(hasText("Like"))
        .performClick()
}

ViewPagers-এ অস্পষ্টতা সমাধান করুন

মেমরিতে একই Compose লেআউট সহ একাধিক ফ্র্যাগমেন্ট একই সাথে থাকলে, আপনি নির্দিষ্ট ফ্র্যাগমেন্টের রুট ভিউ আইডিতে সার্চের স্কোপ সেট করতে পারেন যাতে ম্যাচিংয়ের ক্ষেত্রে কোনও অস্পষ্টতা না থাকে।

@Test
fun testComposeButtonInsideViewPagerItem() = runComposeUiTest {
    // Swipe to the desired page using Espresso
    Espresso.onView(withId(viewPagerViewId)).perform(swipeLeft())

    // Identify the specific container view using Espresso
    val fragmentB = Espresso.onView(withId(fragmentRootViewId))

    // The generic text "Save" is now unique within this view scope
    onRootWithViewInteraction(fragmentB)
        .onNode(hasText("Save"))
        .assertIsDisplayed()
}

UiAutomator-এর সাথে ইন্টারঅপারেবিলিটি

সাধারণত, কম্পোজ করার উপযুক্ত আইটেমগুলি UiAutomator থেকে শুধুমাত্র তাদের সুবিধাজনক বর্ণনাকারীর (দেখানো টেক্সট, কন্টেন্টের বিবরণ ইত্যাদি) মাধ্যমে অ্যাক্সেস করা যায়। আপনি যদি Modifier.testTag ব্যবহার করে এমন কোনও কম্পোজেবল অ্যাক্সেস করতে চান, তাহলে আপনাকে নির্দিষ্ট কম্পোজেবলের সাবট্রির জন্য সিম্যান্টিক প্রপার্টি testTagsAsResourceId চালু করতে হবে। এই আচরণ চালু করা কম্পোজেবলের জন্য উপযোগী যার অন্য কোনও অনন্য হ্যান্ডেল নেই, যেমন স্ক্রোলযোগ্য কম্পোজেবল (যেমন, LazyColumn)।

আপনার কম্পোজেবল হায়ারার্কিতে শুধুমাত্র একবার সিম্যান্টিক প্রপার্টি চালু করুন যাতে Modifier.testTag সহ সব নেস্টেড কম্পোজেবল UiAutomator থেকে অ্যাক্সেস করা যায়।

Scaffold(
    // Enables for all composables in the hierarchy.
    modifier = Modifier.semantics {
        testTagsAsResourceId = true
    }
){
    // Modifier.testTag is accessible from UiAutomator for composables nested here.
    LazyColumn(
        modifier = Modifier.testTag("myLazyColumn")
    ){
        // Content
    }
}

Modifier.testTag(tag)-এর সাথে যেকোনও কম্পোজেবল resourceName-এর মতো একই tag ব্যবহার করে By.res(resourceName)-এর ব্যবহারের মাধ্যমে অ্যাক্সেস করা যেতে পারে।

val device = UiDevice.getInstance(getInstrumentation())

val lazyColumn: UiObject2 = device.findObject(By.res("myLazyColumn"))
// Some interaction with the lazyColumn.

অতিরিক্ত রিসোর্স

  • Android-এ অ্যাপ টেস্ট করা: Android-এ টেস্ট করার মূল ল্যান্ডিং পৃষ্ঠা থেকে টেস্টিংয়ের মূল বিষয় ও টেকনিক সম্পর্কে আরও বিস্তারিত তথ্য পাওয়া যায়।
  • পরীক্ষা করার মূল বিষয়: Android অ্যাপ পরীক্ষা করার পিছনে থাকা মূল ধারণা সম্পর্কে আরও জানুন।
  • লোকাল টেস্ট: আপনি নিজের ওয়ার্কস্টেশনে লোকালি কিছু টেস্ট চালাতে পারবেন।
  • ইনস্ট্রুমেন্টেড টেস্ট: ইনস্ট্রুমেন্টেড টেস্ট রান করানোও একটি ভালো অভ্যাস। অর্থাৎ, সরাসরি ডিভাইসে রান করা টেস্ট।
  • কন্টিনিউয়াস ইন্টিগ্রেশন: কন্টিনিউয়াস ইন্টিগ্রেশন আপনাকে ডিপ্লয়মেন্ট পাইপলাইনে টেস্ট ইন্টিগ্রেট করতে দেয়।
  • বিভিন্ন স্ক্রিন সাইজ টেস্ট করুন: ব্যবহারকারীদের কাছে অনেক ডিভাইস উপলভ্য, তাই আপনাকে বিভিন্ন স্ক্রিন সাইজের জন্য টেস্ট করতে হবে।
  • Espresso: View-ভিত্তিক UI-এর জন্য তৈরি করা হলেও, Espresso-এর জ্ঞান Compose টেস্টিংয়ের কিছু ক্ষেত্রে সহায়ক হতে পারে।