آزمایش کردن قطعه‌ها

این موضوع نحوه گنجاندن میاناهای برنامه‌سازی کاربردی ارائه‌شده توسط چارچوب را در آزمایش‌هایی که رفتار هر تکه را ارزیابی می‌کنند شرح می‌دهد.

قطعه‌ها به‌عنوان محفظه‌های قابل‌استفاده مجدد در برنامه شما عمل می‌کنند و به شما امکان می‌دهند همان چیدمان میانای کاربر را در انواع فعالیت‌ها و پیکربندی‌های چیدمان ارائه دهید. باتوجه‌به تطبیق‌پذیری قطعه‌ها، مهم است که تأیید شود آن‌ها تجربه‌ای یکپارچه و با مصرف بهینه منابع ارائه می‌دهند. به موارد زیر توجه کنید:

  • قطعه شما نباید به فعالیت یا قطعه والد خاصی وابسته باشد.
  • نباید سلسله‌مراتب نمای قطعه را ایجاد کنید، مگراینکه قطعه برای کاربر قابل‌مشاهده باشد.

برای کمک به تنظیم شرایط انجام این آزمایش‌ها، کتابخانه AndroidX fragment-testing کلاس FragmentScenario را برای ایجاد قطعه‌ها و تغییر Lifecycle.State آن‌ها ارائه می‌دهد.

اعلام وابستگی‌ها

برای استفاده از FragmentScenario، مصنوع fragment-testing-manifest را در فایل build.gradle برنامه‌تان بااستفاده از debugImplementation و مصنوع fragment-testing را بااستفاده از androidTestImplementation تعریف کنید، همان‌طور که در مثال زیر نشان داده شده است:

شیار

dependencies {
    def fragment_version = "1.9.1"

    debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version"

    androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version"
}

کاتلین

dependencies {
    val fragment_version = "1.9.1"

    debugImplementation("androidx.fragment:fragment-testing-manifest:$fragment_version")

    androidTestImplementation("androidx.fragment:fragment-testing:$fragment_version")
}

نمونه‌های آزمایشی در این صفحه از ادعاهای کتابخانه‌های Espresso و Truth استفاده می‌کنند. برای کسب اطلاعات درباره دیگر کتابخانه‌های آزمایش و ادعا، به راه‌اندازی پروژه برای AndroidX Test مراجعه کنید.

ایجاد قطعه

FragmentScenario شامل روش‌های زیر برای راه‌اندازی قطعه‌ها در آزمایش‌ها است:

  • launchInContainer()، برای آزمایش میانای کاربر قطعه. FragmentScenario قطعه را به کنترل‌کننده نمای ریشه فعالیت پیوست می‌کند. این فعالیت دربرگیرنده درغیراین‌صورت خالی است.
  • launch()، برای آزمایش بدون میانای کاربر قطعه. FragmentScenario این نوع قطعه را به فعالیت خالی پیوست می‌کند، فعالیتی که نمای ریشه ندارد.

پس‌از راه‌اندازی یکی از این انواع قطعه، FragmentScenario قطعه تحت آزمایش را به حالت مشخصی هدایت می‌کند. به‌طور پیش‌فرض این حالت RESUMED است، اما می‌توانید آن را با آرگومان initialState لغو کنید. وضعیت RESUMED نشان می‌دهد که قطعه درحال اجرا است و برای کاربر قابل‌مشاهده است. می‌توانید اطلاعات مربوط به عناصر میانای کاربر آن را بااستفاده از آزمایش‌های Espresso UI ارزیابی کنید.

نمونه کدهای زیر نحوه راه‌اندازی قطعه را بااستفاده از هر روش نشان می‌دهد:

نمونه launchInContainer()‎

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        // The "fragmentArgs" argument is optional.
        val fragmentArgs = bundleOf(“selectedListItem” to 0)
        val scenario = launchFragmentInContainer<EventFragment>(fragmentArgs)
        ...
    }
}

نمونه()launch

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        // The "fragmentArgs" arguments are optional.
        val fragmentArgs = bundleOf("numElements" to 0)
        val scenario = launchFragment<EventFragment>(fragmentArgs)
        ...
    }
}

ارائه وابستگی‌ها

اگر قطعه‌هایتان وابستگی دارند، می‌توانید نسخه‌های آزمایشی این وابستگی‌ها را با ارائه یک FragmentFactory سفارشی به روش‌های launchInContainer() یا launch() ارائه دهید.

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val someDependency = TestDependency()
        launchFragmentInContainer {
            EventFragment(someDependency)
        }
        ...
    }
}

برای اطلاعات بیشتر درباره استفاده از FragmentFactory برای ارائه وابستگی‌ها به قطعه‌ها، به مدیر قطعه مراجعه کنید.

انتقال قطعه به حالت جدید

در آزمایش‌های میانای کاربر برنامه‌تان، معمولاً کافی است قطعه تحت آزمایش را راه‌اندازی کنید و آزمایش آن را از حالت RESUMED شروع کنید. اما در آزمایش‌های واحد با جزئیات بیشتر، ممکن است رفتار قطعه را هنگام انتقال از یک حالت چرخه حیات به حالت دیگر نیز ارزیابی کنید. می‌توانید با ارسال آرگومان initialState به هریک از توابع launchFragment*()، وضعیت اولیه را مشخص کنید.

برای هدایت قطعه به حالت چرخه حیات متفاوت، moveToState() را فراخوانی کنید. این روش از حالت‌های زیر به‌عنوان متغیر مستقل پشتیبانی می‌کند: CREATED، STARTED، RESUMED، و DESTROYED. این روش وضعیتی را شبیه‌سازی می‌کند که در آن قطعه یا فعالیتی که حاوی قطعه شما است، به هر دلیلی وضعیت خود را تغییر می‌دهد.

مثال زیر یک قطعه آزمایشی را در حالت INITIALIZED راه‌اندازی می‌کند و سپس آن را به حالت RESUMED منتقل می‌کند:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<EventFragment>(
            initialState = Lifecycle.State.INITIALIZED
        )
        // EventFragment has gone through onAttach(), but not onCreate().
        // Verify the initial state.
        scenario.moveToState(Lifecycle.State.RESUMED)
        // EventFragment moves to CREATED -> STARTED -> RESUMED.
        ...
    }
}

بازآفرینی بخش

اگر برنامه‌تان در دستگاهی اجرا می‌شود که منابع کمی دارد، ممکن است سیستم فعالیتی را که حاوی قطعه شما است ازبین ببرد. در این شرایط، برنامه شما باید هنگام بازگشت کاربر به آن، قطعه را دوباره ایجاد کند. برای شبیه‌سازی این وضعیت، recreate() را فراخوانی کنید:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<EventFragment>()
        scenario.recreate()
        ...
    }
}

FragmentScenario.recreate() قطعه و میزبان آن را ازبین می‌برد و سپس آن‌ها را دوباره ایجاد می‌کند. وقتی کلاس FragmentScenario قطعه تحت آزمایش را بازسازی می‌کند، قطعه به حالت چرخه حیاتی که قبل‌از نابود شدن در آن بود برمی‌گردد.

تعامل با قطعه‌های واسط کاربر

برای راه‌اندازی کنش‌های میانای کاربر در قطعه تحت آزمایش، از تطبیق‌دهنده‌های نمای Espresso برای تعامل با عناصر در نمای خود استفاده کنید:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<EventFragment>()
        onView(withId(R.id.refresh)).perform(click())
        // Assert some expected behavior
        ...
    }
}

اگر لازم است روشی را در خود قطعه فراخوانی کنید، مثلاً پاسخ دادن به انتخابی در منوِ گزینه‌ها، می‌توانید این کار را به‌طور ایمن با دریافت مرجعی به قطعه بااستفاده از FragmentScenario.onFragment() و ارسال FragmentAction انجام دهید:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<EventFragment>()
        scenario.onFragment { fragment ->
            fragment.myInstanceMethod()
        }
    }
}

آزمایش کنش‌های کادر گفت‌وگو

‫FragmentScenario از آزمایش قطعه‌های گفتگو نیز پشتیبانی می‌کند. اگرچه قطعه‌های گفتگو دارای عناصر میانای کاربر هستند، چیدمان آن‌ها در پنجره‌ای جداگانه پر می‌شود، نه در خود فعالیت. به همین دلیل، از FragmentScenario.launch() برای آزمایش قطعه‌های کادر گفتگو استفاده کنید.

مثال زیر فرایند بستن کادر گفتگو را آزمایش می‌کند:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testDismissDialogFragment() {
        // Assumes that "MyDialogFragment" extends the DialogFragment class.
        with(launchFragment<MyDialogFragment>()) {
            onFragment { fragment ->
                assertThat(fragment.dialog).isNotNull()
                assertThat(fragment.requireDialog().isShowing).isTrue()
                fragment.dismiss()
                fragment.parentFragmentManager.executePendingTransactions()
                assertThat(fragment.dialog).isNull()
            }
        }

        // Assumes that the dialog had a button
        // containing the text "Cancel".
        onView(withText("Cancel")).check(doesNotExist())
    }
}