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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule var activityScenarioRule = activityScenarioRule<MyActivity>()

    @Test fun testEvent() {
        val scenario = activityScenarioRule.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 خود، همانطور که در قطعه کد زیر نشان داده شده است، دریافت کنید:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testResult() {
        launchActivity<MyActivity>().use {
            onView(withId(R.id.finish_button)).perform(click())

            // Activity under test is now finished.

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

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

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

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use {
            onView(withId(R.id.refresh)).perform(click())
        }
    }
}

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

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