الگوهای رایج

شما می‌توانید برنامه Compose خود را با رویکردها و الگوهای تثبیت‌شده آزمایش کنید.

تست در انزوا

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

این به این معنی نیست که شما فقط باید تست‌های رابط کاربری واحد ایجاد کنید. تست‌های رابط کاربری که بخش‌های بزرگتری از رابط کاربری شما را پوشش می‌دهند نیز بسیار مهم هستند.

پس از تنظیم محتوای خود، به فعالیت و منابع دسترسی پیدا کنید

اغلب اوقات شما نیاز دارید محتوای تحت آزمایش را با استفاده از composeTestRule.setContent تنظیم کنید و همچنین باید به منابع اکتیویتی دسترسی داشته باشید، برای مثال برای اینکه مشخص کنید متن نمایش داده شده با یک منبع رشته‌ای مطابقت دارد یا خیر. با این حال، اگر اکتیویتی از قبل setContent را فراخوانی کرده باشد، نمی‌توانید آن را روی قانونی که با createAndroidComposeRule() ایجاد شده است، فراخوانی کنید.

یک الگوی رایج برای دستیابی به این هدف، ایجاد یک AndroidComposeTestRule با استفاده از یک activity خالی مانند ComponentActivity است.

class MyComposeTest {

    @get:Rule
    val composeTestRule = createAndroidComposeRule<ComponentActivity>()

    @Test
    fun myTest() {
        // Start the app
        composeTestRule.setContent {
            MyAppTheme {
                MainScreen(uiState = exampleUiState, /*...*/)
            }
        }
        val continueLabel = composeTestRule.activity.getString(R.string.next)
        composeTestRule.onNodeWithText(continueLabel).performClick()
    }
}

توجه داشته باشید که ComponentActivity باید به فایل AndroidManifest.xml برنامه شما اضافه شود. با اضافه کردن این وابستگی به ماژول خود، آن را فعال کنید:

debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")

ویژگی‌های معنایی سفارشی

شما می‌توانید ویژگی‌های معنایی سفارشی ایجاد کنید تا اطلاعات را در معرض تست‌ها قرار دهید. برای انجام این کار، یک SemanticsPropertyKey جدید تعریف کنید و آن را با استفاده از SemanticsPropertyReceiver در دسترس قرار دهید.

// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey

حالا از آن ویژگی در اصلاح‌کننده‌ی semantics استفاده کنید:

val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
    modifier = Modifier.semantics { pickedDate = datePickerValue }
)

از تست‌ها، از SemanticsMatcher.expectValue برای تعیین مقدار ویژگی استفاده کنید:

composeTestRule
    .onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
    .assertExists()

تأیید بازیابی وضعیت

تأیید کنید که وضعیت عناصر Compose شما هنگام ایجاد مجدد فعالیت یا فرآیند، به درستی بازیابی می‌شود. چنین بررسی‌هایی را بدون تکیه بر بازسازی فعالیت با کلاس StateRestorationTester انجام دهید.

این کلاس به شما امکان می‌دهد تا بازسازی یک composable را شبیه‌سازی کنید. این کلاس به ویژه برای تأیید پیاده‌سازی rememberSaveable مفید است.


class MyStateRestorationTests {

    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun onRecreation_stateIsRestored() {
        val restorationTester = StateRestorationTester(composeTestRule)

        restorationTester.setContent { MainScreen() }

        // TODO: Run actions that modify the state

        // Trigger a recreation
        restorationTester.emulateSavedInstanceStateRestore()

        // TODO: Verify that state has been correctly restored.
    }
}

تنظیمات مختلف دستگاه را آزمایش کنید

برنامه‌های اندروید باید با بسیاری از شرایط متغیر سازگار شوند: اندازه پنجره‌ها، مکان‌ها، اندازه فونت‌ها، تم‌های تیره و روشن و موارد دیگر. بیشتر این شرایط از مقادیر سطح دستگاه که توسط کاربر کنترل می‌شوند و با نمونه Configuration فعلی نمایش داده می‌شوند، مشتق می‌شوند. آزمایش پیکربندی‌های مختلف به طور مستقیم در یک تست دشوار است زیرا تست باید ویژگی‌های سطح دستگاه را پیکربندی کند.

DeviceConfigurationOverride یک API فقط آزمایشی است که به شما امکان می‌دهد پیکربندی‌های مختلف دستگاه را به صورت محلی برای محتوای @Composable تحت آزمایش شبیه‌سازی کنید.

شیء همراه DeviceConfigurationOverride دارای توابع افزونه زیر است که ویژگی‌های پیکربندی سطح دستگاه را لغو می‌کنند:

برای اعمال یک override خاص، محتوای مورد آزمایش را در یک فراخوانی به تابع سطح بالای DeviceConfigurationOverride() قرار دهید و override را به عنوان پارامتر apply ارسال کنید.

برای مثال، کد زیر، تابع DeviceConfigurationOverride.ForcedSize() را برای تغییر چگالی به صورت محلی اعمال می‌کند و باعث می‌شود که MyScreen composable در یک پنجره بزرگ افقی رندر شود، حتی اگر دستگاهی که تست روی آن اجرا می‌شود، مستقیماً از آن اندازه پنجره پشتیبانی نکند:

composeTestRule.setContent {
    DeviceConfigurationOverride(
        DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))
    ) {
        MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping.
    }
}

برای اعمال چندین override با هم، از DeviceConfigurationOverride.then() استفاده کنید:

composeTestRule.setContent {
    DeviceConfigurationOverride(
        DeviceConfigurationOverride.FontScale(1.5f) then
            DeviceConfigurationOverride.FontWeightAdjustment(200)
    ) {
        Text(text = "text with increased scale and weight")
    }
}

منابع اضافی

  • تست برنامه‌ها در اندروید : صفحه اصلی تست اندروید، نمای وسیع‌تری از اصول و تکنیک‌های تست ارائه می‌دهد.
  • اصول اولیه تست : درباره مفاهیم اصلی پشت تست یک برنامه اندروید بیشتر بدانید.
  • تست‌های محلی : شما می‌توانید برخی از تست‌ها را به صورت محلی، روی ایستگاه کاری خودتان اجرا کنید.
  • تست‌های ابزاری : اجرای تست‌های ابزاری نیز روش خوبی است. یعنی تست‌هایی که مستقیماً روی دستگاه اجرا می‌شوند.
  • ادغام مداوم : ادغام مداوم به شما امکان می‌دهد تست‌های خود را در خط تولید خود ادغام کنید.
  • آزمایش اندازه‌های مختلف صفحه نمایش : با توجه به اینکه دستگاه‌های زیادی در دسترس کاربران است، باید اندازه‌های مختلف صفحه نمایش را آزمایش کنید.
  • Espresso : اگرچه برای رابط‌های کاربری مبتنی بر View در نظر گرفته شده است، اما دانش Espresso همچنان می‌تواند برای برخی از جنبه‌های تست Compose مفید باشد.