الگوهای رایج

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

آزمایش در انزوا

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

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

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

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

الگوی رایج برای دستیابی به این هدف ایجاد AndroidComposeTestRule بااستفاده از فعالیت خالی مثل 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 انجام دهید.

این کلاس به شما امکان می‌دهد بازآفرینی یک عنصر ترکیبی را شبیه‌سازی کنید. این ابزار به‌ویژه برای درستی‌سنجی پیاده‌سازی 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.
    }
}

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

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

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

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

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

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

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

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

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

مدیریت خطای سفارشی در آزمایش‌ها

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

‫Compose خط لوله مدیریت خطای بومی‌ای برای کارآمدتر کردن تشخیص خرابی ارائه می‌دهد. می‌توانید درصورت خرابی، به‌طور خودکار نماگرفت‌ها و سلسله‌مراتب واسط کاربر را ضبط کنید، یا کارگزارهای سفارشی را ثبت کنید تا تله‌متری خرابی را به ابزارهای خارجی ارسال کنید.

پیکربندی مدیریت خطا

برای پیکربندی مدیریت خطا، یک شیء TestFailurePolicy را به ComposeUiTestConfig ارسال کنید.

ضبط کردن داده‌های خطای داخلی

برای ضبط نماگرفت‌ها و سلسله‌مراتب میانای کاربری درصورت ناموفق بودن آزمایش، ویژگی‌های screenshotCaptureMode و uiHierarchyCaptureMode را در TestFailurePolicy تنظیم کنید.

class MyComposeTest {
    private val customConfig = ComposeUiTestConfig(
        failurePolicy = TestFailurePolicy(
            screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled,
            uiHierarchyCaptureMode = TestFailurePolicy.CaptureMode.Enabled
        )
    )

    @Test
    fun myFirstTest() = runComposeUiTest(config = customConfig) {
        // ...
    }
}

استفاده از مدیریت‌کننده خطای سفارشی

برای تعریف رفتار سفارشی برای خطاهای آزمایش، TestFailureHandler را به failureHandlers فهرست اضافه کنید. هر کنترل‌کننده شیء FailureContext را دریافت می‌کند که حاوی خطای اصلی و فهرستی از آرتیفکت‌های تولیدشده توسط کنترل‌کننده‌های خط لوله قبلی است.

class MyComposeTestWithHandler {
    private val customConfig = ComposeUiTestConfig(
        failurePolicy = TestFailurePolicy(
            screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled,
            failureHandlers = listOf(
                TestFailureHandler { context ->
                    val screenshot = context.artifacts.firstOrNull {
                        it.type == FailureArtifact.Type.Screenshot
                    }
                    // ...
                }
            )
        )
    )

    @get:Rule
    val rule = createComposeRule(config = customConfig)

    // ...
}

پیکربندی ضبط‌ها برای کل مجموعه آزمایش

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

// build.gradle.kts
android {
    defaultConfig {
        // ...
        testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isUiHierarchyCaptureEnabled"] = "true"
        testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isScreenshotCaptureEnabled"] = "true"
    }
}

اولویت پیکربندی

این چارچوب هم TestFailurePolicy محلی و هم آرگومان‌های اجراکننده سطح مجموعه را ارزیابی می‌کند:

  • اگر حالت CaptureMode.Enabled/Disabled را به‌طور صریح در آزمایش failurePolicy تنظیم کنید، این حالت بر آرگومان اجراکننده اولویت دارد.
  • اگر حالت را روی CaptureMode.Unspecified تنظیم کنید (یا failurePolicy را روی null بگذارید)، چارچوب به آرگومان اجراکننده برمی‌گردد.

منابع تکمیلی

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