فعالیت های برنامه خود را آزمایش کنید

فعالیت‌ها به عنوان ظرف‌هایی برای هر تعامل کاربر در برنامه شما عمل می‌کنند، بنابراین آزمایش نحوه رفتار فعالیت‌های برنامه شما در طول رویدادهای سطح دستگاه مانند موارد زیر مهم است:

  • یک برنامه دیگر، مانند برنامه تلفن دستگاه، فعالیت برنامه شما را قطع می‌کند.
  • سیستم، اکتیویتی شما را از بین می‌برد و دوباره ایجاد می‌کند.
  • کاربر فعالیت شما را در یک محیط پنجره‌بندی جدید، مانند تصویر در تصویر (PIP) یا چند پنجره‌ای، قرار می‌دهد.

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

این راهنما نحوه ارزیابی توانایی برنامه شما در حفظ یکپارچگی داده‌ها و ارائه یک تجربه کاربری خوب را در حین گذار فعالیت‌های برنامه از حالت‌های مختلف در چرخه عمرشان شرح می‌دهد.

فعالیت‌های تست در Compose

هنگام آزمایش یک برنامه ساخته شده با Jetpack Compose، معمولاً از createAndroidComposeRule برای راه‌اندازی اکتیویتی و تعامل با اجزای رابط کاربری خود استفاده می‌کنید.

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

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

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

@Test fun testEvent() {
    val scenario = composeTestRule.activityRule.scenario

    // ...
}

مدیریت وضعیت یک فعالیت

یکی از جنبه‌های کلیدی تست فعالیت‌های برنامه شما، قرار دادن فعالیت‌های برنامه در حالت‌های خاص است. برای تعریف این بخش "داده‌شده" از تست‌های خود، از نمونه‌های ActivityScenario ، بخشی از کتابخانه AndroidX Test ، استفاده کنید. با استفاده از این کلاس، می‌توانید فعالیت خود را در حالت‌هایی قرار دهید که رویدادهای سطح دستگاه را شبیه‌سازی می‌کنند.

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

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

ایجاد یک فعالیت

برای ایجاد اکتیویتی تحت آزمایش، کد نشان داده شده در قطعه کد زیر را اضافه کنید:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
       launchActivity<MyActivity>().use {
       }
    }
}

پس از ایجاد اکتیویتی، ActivityScenario آن را به حالت RESUMED منتقل می‌کند. این حالت نشان می‌دهد که اکتیویتی شما در حال اجرا است و برای کاربران قابل مشاهده است. در این حالت، شما می‌توانید با استفاده از Composable های اکتیویتی خود با استفاده از Compose testing APIs تعامل داشته باشید.

گوگل توصیه می‌کند که پس از اتمام تست، تابع close را روی اکتیویتی فراخوانی کنید. این کار منابع مرتبط را پاک‌سازی کرده و پایداری تست‌های شما را بهبود می‌بخشد. ActivityScenario Closeable استفاده می‌کند، بنابراین می‌توانید افزونه use را اعمال کنید تا اکتیویتی به طور خودکار بسته شود.

به عنوان یک روش جایگزین، می‌توانید از createAndroidComposeRule برای اجرای خودکار اکتیویتی قبل از هر تست، مدیریت teardown و اعطای دسترسی به هر دو متد تست رابط کاربری Compose و ActivityScenario استفاده کنید. مثال زیر نحوه تعریف یک قانون و دریافت نمونه‌ای از یک سناریو از آن را نشان می‌دهد:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        val scenario = composeTestRule.activityRule.scenario
    }
}

فعالیت را به حالت جدید هدایت کنید

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

یک نمونه از کاربرد moveToState در قطعه کد زیر آمده است:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.moveToState(State.CREATED)
        }
    }
}

تعیین وضعیت فعلی فعالیت

برای تعیین وضعیت فعلی یک فعالیت تحت آزمایش، مقدار فیلد state را در شیء ActivityScenario خود دریافت کنید. بررسی وضعیت یک فعالیت تحت آزمایش، در صورتی که فعالیت به فعالیت دیگری هدایت شود یا خود را به پایان برساند، بسیار مفید است، همانطور که در قطعه کد زیر نشان داده شده است:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              startActivity(Intent(activity, MyOtherActivity::class.java))
            }

            val originalActivityState = scenario.state
        }
    }
}

فعالیت را از نو بسازید

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.recreate()
        }
    }
}

کلاس ActivityScenario وضعیت نمونه ذخیره شده اکتیویتی و هر شیء حاشیه نویسی شده با استفاده از @NonConfigurationInstance را نگهداری می‌کند. این اشیاء در نمونه جدید اکتیویتی تحت آزمایش شما بارگذاری می‌شوند.

بازیابی نتایج فعالیت

برای دریافت کد نتیجه یا داده‌های مرتبط با یک فعالیت پایان‌یافته، مقدار فیلد result را در شیء ActivityScenario خود دریافت کنید. با استفاده از createAndroidComposeRule ، می‌توانید به راحتی عملکرد رابط کاربری را که فعالیت را به پایان می‌رساند، فعال کنید، همانطور که در قطعه کد زیر نشان داده شده است:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testResult() {
        composeTestRule.onNodeWithTag("finish_button").performClick()

        val scenario = composeTestRule.activityRule.scenario
        val resultCode = scenario.result.resultCode
        val resultData = scenario.result.resultData
    }
}

فعال کردن اقدامات در فعالیت

تمام متدهای درون ActivityScenario فراخوانی‌ها را مسدود می‌کنند، بنابراین API از شما می‌خواهد که آنها را در thread instrumentation اجرا کنید.

برای فعال کردن اکشن‌ها در اکتیویتی تحت آزمایش خود، از APIهای تست Compose برای تعامل با کامپوننت‌های خود استفاده کنید:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        composeTestRule.onNodeWithText("Refresh").performClick()
    }
}

با این حال، اگر نیاز به فراخوانی یک متد روی خود اکتیویتی دارید، می‌توانید با استفاده از onActivity این کار را با خیال راحت انجام دهید:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              activity.handleSwipeToRefresh()
            }
        }
    }
}

منابع اضافی

برای اطلاعات بیشتر در مورد آزمایش، به منابع اضافی زیر مراجعه کنید:

مستندات