আপনার অ্যাপ্লিকেশানটি আপনার প্রত্যাশা অনুযায়ী কাজ করে কিনা তা যাচাই করার জন্য শিপ করার আগে আপনার অ্যাপের নেভিগেশন লজিক পরীক্ষা করা গুরুত্বপূর্ণ।
ন্যাভিগেশন উপাদানটি গন্তব্যের মধ্যে নেভিগেশন পরিচালনা, আর্গুমেন্ট পাস করা এবং FragmentManager
এর সাথে কাজ করার সমস্ত কাজ পরিচালনা করে। এই ক্ষমতাগুলি ইতিমধ্যেই কঠোরভাবে পরীক্ষা করা হয়েছে, তাই আপনার অ্যাপে সেগুলি আবার পরীক্ষা করার প্রয়োজন নেই৷ যাইহোক, আপনার টুকরোগুলিতে থাকা অ্যাপ নির্দিষ্ট কোড এবং তাদের NavController
এর মধ্যে মিথস্ক্রিয়াগুলি পরীক্ষা করা গুরুত্বপূর্ণ। এই নির্দেশিকাটি কয়েকটি সাধারণ নেভিগেশন পরিস্থিতির মধ্য দিয়ে চলে এবং কীভাবে সেগুলি পরীক্ষা করা যায়।
পরীক্ষা খণ্ড নেভিগেশন
বিচ্ছিন্নভাবে তাদের NavController
সাথে ফ্র্যাগমেন্ট ইন্টারঅ্যাকশন পরীক্ষা করতে, নেভিগেশন 2.3 এবং উচ্চতর একটি TestNavHostController
প্রদান করে যা বর্তমান গন্তব্য সেট করার জন্য API প্রদান করে এবং NavController.navigate()
অপারেশনের পরে ব্যাক স্ট্যাক যাচাই করে।
আপনি আপনার অ্যাপ মডিউলের build.gradle
ফাইলে নিম্নলিখিত নির্ভরতা যোগ করে আপনার প্রকল্পে নেভিগেশন টেস্টিং আর্টিফ্যাক্ট যোগ করতে পারেন:
গ্রোভি
dependencies { def nav_version = "2.7.7" androidTestImplementation "androidx.navigation:navigation-testing:$nav_version" }
কোটলিন
dependencies { val nav_version = "2.7.7" androidTestImplementation("androidx.navigation:navigation-testing:$nav_version") }
ধরা যাক আপনি একটি ট্রিভিয়া গেম তৈরি করছেন। গেমটি একটি টাইটেল_স্ক্রিন দিয়ে শুরু হয় এবং ব্যবহারকারী প্লে ক্লিক করলে একটি ইন_গেম স্ক্রিনে নেভিগেট হয়।
শিরোনাম_স্ক্রীনের প্রতিনিধিত্বকারী খণ্ডটি এইরকম দেখতে পারে:
কোটলিন
class TitleScreen : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ) = inflater.inflate(R.layout.fragment_title_screen, container, false) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { view.findViewById<Button>(R.id.play_btn).setOnClickListener { view.findNavController().navigate(R.id.action_title_screen_to_in_game) } } }
জাভা
public class TitleScreen extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_title_screen, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { view.findViewById(R.id.play_btn).setOnClickListener(v -> { Navigation.findNavController(view).navigate(R.id.action_title_screen_to_in_game); }); } }
ব্যবহারকারী প্লে-তে ক্লিক করলে অ্যাপটি সঠিকভাবে ব্যবহারকারীকে in_game স্ক্রিনে নেভিগেট করে তা পরীক্ষা করার জন্য, আপনার পরীক্ষাটি যাচাই করতে হবে যে এই অংশটি সঠিকভাবে NavController
কে R.id.in_game
স্ক্রিনে নিয়ে গেছে।
FragmentScenario
, Espresso , এবং TestNavHostController
এর সংমিশ্রণ ব্যবহার করে, আপনি এই দৃশ্যটি পরীক্ষা করার জন্য প্রয়োজনীয় শর্তগুলি পুনরায় তৈরি করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:
কোটলিন
@RunWith(AndroidJUnit4::class) class TitleScreenTest { @Test fun testNavigationToInGameScreen() { // Create a TestNavHostController val navController = TestNavHostController( ApplicationProvider.getApplicationContext()) // Create a graphical FragmentScenario for the TitleScreen val titleScenario = launchFragmentInContainer<TitleScreen>() titleScenario.onFragment { fragment -> // Set the graph on the TestNavHostController navController.setGraph(R.navigation.trivia) // Make the NavController available via the findNavController() APIs Navigation.setViewNavController(fragment.requireView(), navController) } // Verify that performing a click changes the NavController’s state onView(ViewMatchers.withId(R.id.play_btn)).perform(ViewActions.click()) assertThat(navController.currentDestination?.id).isEqualTo(R.id.in_game) } }
জাভা
@RunWith(AndroidJUnit4.class) public class TitleScreenTestJava { @Test public void testNavigationToInGameScreen() { // Create a TestNavHostController TestNavHostController navController = new TestNavHostController( ApplicationProvider.getApplicationContext()); // Create a graphical FragmentScenario for the TitleScreen FragmentScenario<TitleScreen> titleScenario = FragmentScenario.launchInContainer(TitleScreen.class); titleScenario.onFragment(fragment -> // Set the graph on the TestNavHostController navController.setGraph(R.navigation.trivia); // Make the NavController available via the findNavController() APIs Navigation.setViewNavController(fragment.requireView(), navController) ); // Verify that performing a click changes the NavController’s state onView(ViewMatchers.withId(R.id.play_btn)).perform(ViewActions.click()); assertThat(navController.currentDestination.id).isEqualTo(R.id.in_game); } }
উপরের উদাহরণটি TestNavHostController
এর একটি উদাহরণ তৈরি করে এবং এটিকে খণ্ডটিতে বরাদ্দ করে। এটি তখন UI চালাতে Espresso ব্যবহার করে এবং যাচাই করে যে উপযুক্ত নেভিগেশন ব্যবস্থা নেওয়া হয়েছে।
একটি বাস্তব NavController
এর মতই, TestNavHostController
আরম্ভ করার জন্য আপনাকে setGraph
কল করতে হবে। এই উদাহরণে, খণ্ডটি পরীক্ষা করা হচ্ছে আমাদের গ্রাফের শুরুর গন্তব্য। TestNavHostController
একটি setCurrentDestination
পদ্ধতি প্রদান করে যা আপনাকে বর্তমান গন্তব্য (এবং ঐচ্ছিকভাবে, সেই গন্তব্যের জন্য আর্গুমেন্ট) সেট করতে দেয় যাতে আপনার পরীক্ষা শুরু হওয়ার আগে NavController
সঠিক অবস্থায় থাকে।
একটি NavHostController
উদাহরণের বিপরীতে যা একটি NavHostFragment
ব্যবহার করবে, TestNavHostController
অন্তর্নিহিত navigate()
আচরণকে ট্রিগার করে না (যেমন FragmentTransaction
যা FragmentNavigator
করে) যখন আপনি navigate()
কল করেন - এটি শুধুমাত্র TestNavHostController
এর অবস্থা আপডেট করে।
FragmentScenario সহ NavigationUI পরীক্ষা করুন
পূর্ববর্তী উদাহরণে, titleScenario.onFragment()
কে প্রদত্ত কলব্যাকটি তার জীবনচক্রের মধ্য দিয়ে RESUMED
অবস্থায় চলে যাওয়ার পরে বলা হয়। এই সময়ের মধ্যে, খণ্ডটির দৃশ্য ইতিমধ্যে তৈরি এবং সংযুক্ত করা হয়েছে, তাই সঠিকভাবে পরীক্ষা করতে জীবনচক্রে খুব দেরি হতে পারে। উদাহরণ স্বরূপ, আপনার খণ্ডের ভিউ সহ NavigationUI
ব্যবহার করার সময়, যেমন আপনার খণ্ড দ্বারা নিয়ন্ত্রিত একটি Toolbar
দিয়ে, আপনি খণ্ডটি RESUMED
অবস্থায় পৌঁছানোর আগে আপনার NavController
এর সাথে সেটআপ পদ্ধতিগুলি কল করতে পারেন৷ সুতরাং, জীবনচক্রের আগে আপনার TestNavHostController
সেট করার জন্য আপনার একটি উপায় প্রয়োজন।
একটি টুকরো যার নিজস্ব Toolbar
মালিক তা নিম্নরূপ লেখা যেতে পারে:
কোটলিন
class TitleScreen : Fragment(R.layout.fragment_title_screen) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val navController = view.findNavController() view.findViewById<Toolbar>(R.id.toolbar).setupWithNavController(navController) } }
জাভা
public class TitleScreen extends Fragment { public TitleScreen() { super(R.layout.fragment_title_screen); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { NavController navController = Navigation.findNavController(view); view.findViewById(R.id.toolbar).setupWithNavController(navController); } }
এখানে আমাদের প্রয়োজন onViewCreated()
কল করার সময় দ্বারা তৈরি করা NavController
। onFragment()
এর আগের পদ্ধতি ব্যবহার করা আমাদের TestNavHostController
লাইফসাইকেলে অনেক দেরী করে দেবে, যার ফলে findNavController()
কল ব্যর্থ হবে।
FragmentScenario
একটি FragmentFactory
ইন্টারফেস অফার করে যা জীবনচক্র ইভেন্টের জন্য কলব্যাক নিবন্ধন করতে ব্যবহার করা যেতে পারে। এটি একটি কলব্যাক পেতে Fragment.getViewLifecycleOwnerLiveData()
এর সাথে মিলিত হতে পারে যা অবিলম্বে onCreateView()
অনুসরণ করে, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:
কোটলিন
val scenario = launchFragmentInContainer { TitleScreen().also { fragment -> // In addition to returning a new instance of our Fragment, // get a callback whenever the fragment’s view is created // or destroyed so that we can set the NavController fragment.viewLifecycleOwnerLiveData.observeForever { viewLifecycleOwner -> if (viewLifecycleOwner != null) { // The fragment’s view has just been created navController.setGraph(R.navigation.trivia) Navigation.setViewNavController(fragment.requireView(), navController) } } } }
জাভা
FragmentScenario<TitleScreen> scenario = FragmentScenario.launchInContainer( TitleScreen.class, null, new FragmentFactory() { @NonNull @Override public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className, @Nullable Bundle args) { TitleScreen titleScreen = new TitleScreen(); // In addition to returning a new instance of our fragment, // get a callback whenever the fragment’s view is created // or destroyed so that we can set the NavController titleScreen.getViewLifecycleOwnerLiveData().observeForever(new Observer<LifecycleOwner>() { @Override public void onChanged(LifecycleOwner viewLifecycleOwner) { // The fragment’s view has just been created if (viewLifecycleOwner != null) { navController.setGraph(R.navigation.trivia); Navigation.setViewNavController(titleScreen.requireView(), navController); } } }); return titleScreen; } });
এই কৌশলটি ব্যবহার করে, onViewCreated()
কল করার আগে NavController
পাওয়া যায়, যা ক্র্যাশ না করেই NavigationUI
পদ্ধতি ব্যবহার করার অনুমতি দেয়।
ব্যাক স্ট্যাক এন্ট্রির সাথে ইন্টারঅ্যাকশন পরীক্ষা করা
ব্যাক স্ট্যাক এন্ট্রিগুলির সাথে ইন্টারঅ্যাক্ট করার সময়, TestNavHostController
আপনাকে NavHostController
থেকে উত্তরাধিকারসূত্রে পাওয়া APIগুলি ব্যবহার করে আপনার নিজস্ব পরীক্ষা LifecycleOwner
, ViewModelStore
এবং OnBackPressedDispatcher
এর সাথে কন্ট্রোলারকে সংযুক্ত করতে দেয়।
উদাহরণস্বরূপ, একটি ন্যাভিগেশন স্কোপড ViewModel ব্যবহার করে এমন একটি খণ্ড পরীক্ষা করার সময়, আপনাকে অবশ্যই TestNavHostController
এ setViewModelStore
কল করতে হবে:
কোটলিন
val navController = TestNavHostController(ApplicationProvider.getApplicationContext()) // This allows fragments to use by navGraphViewModels() navController.setViewModelStore(ViewModelStore())
জাভা
TestNavHostController navController = new TestNavHostController(ApplicationProvider.getApplicationContext()); // This allows fragments to use new ViewModelProvider() with a NavBackStackEntry navController.setViewModelStore(new ViewModelStore())
সম্পর্কিত বিষয়
- ইন্সট্রুমেন্টেড ইউনিট টেস্ট তৈরি করুন - কীভাবে আপনার ইন্সট্রুমেন্টেড টেস্ট স্যুট সেটআপ করবেন এবং অ্যান্ড্রয়েড ডিভাইসে পরীক্ষা চালাবেন তা শিখুন।
- Espresso - Espresso দিয়ে আপনার অ্যাপের UI পরীক্ষা করুন।
- AndroidX পরীক্ষার সাথে JUnit4 নিয়ম - আরও নমনীয়তা প্রদান করতে এবং পরীক্ষায় প্রয়োজনীয় বয়লারপ্লেট কোড কমাতে AndroidX টেস্ট লাইব্রেরির সাথে JUnit 4 নিয়মগুলি ব্যবহার করুন৷
- আপনার অ্যাপ্লিকেশানের টুকরোগুলি পরীক্ষা করুন -
FragmentScenario
সাথে বিচ্ছিন্নভাবে আপনার অ্যাপ্লিকেশানের খণ্ডগুলি কীভাবে পরীক্ষা করবেন তা শিখুন৷ - AndroidX টেস্টের জন্য প্রজেক্ট সেট আপ করুন - AndroidX টেস্ট ব্যবহার করার জন্য আপনার অ্যাপের প্রোজেক্ট ফাইলগুলিতে প্রয়োজনীয় লাইব্রেরিগুলি কীভাবে ঘোষণা করবেন তা শিখুন।