Source: https://unsplash.com/photos/turned-on-android-smartphone-t8TOMKe6xZU

Before we talk about how to assert intent data consumption in instrumented tests, we need to talk about why it’s crucial.

Consider a scenario where your composables access an intent extra. You might wanna verify that your composables can display the value coming from the intent correctly.

val text = intent.getStringExtra(Intent.EXTRA_TEXT) ?: "no extra text"
Text(name = text)

What’s more likely to happen in real-world scenarios is that your Activity will access the intent extras, pass them over to ViewModel and ViewModel will compute based on the input and set the UI state.

The question is, how do we assert that the intent extras are consumed correctly if we wanna avoid the high cost of manual testing?

If you Google for a solution, ComposeTestRule, provided by Jetpack, is most likely the first thing you’ll find. There are two main ways to create a ComposeTestRule: createComposeRule and createAndroidComposeRule.

createAndroidComposeRule is the tool of choice if you want to launch your own Activity, but createAndroidComposeRule takes only two parameters, as you can see in the screenshot below taken from the Jetpack’s official Compose test library.

A Function From Official Compose Test Library

This means there’s no straightforward way to launch an Activity with your own intent using the tools provided by Jetpack in order to assert composables in the Activity.

That’s the problem ComposeUiTest solves. This library uses the official Compose test library under the hood and provides easy-to-use functions for developer friendliness.

Let’s take a look at how easy it is to use the library.

First, import the library.

dependencies {
androidTestImplementation("io.github.aungthiha:compose-ui-test:1.0.1")
}

In your test case, you can pass in your intent to start an Activity and in the trailing lambda, you can assert your composables.

You can also directly use ActivityScenario to launch an Activity the way you prefer.

But wait, what if you need to start all test cases with the same intent? Repeating runAndroidComposeUiTest in all the test cases would be cumbersome. For that, we can create a test rule using createAndroidComposeRule. Yes, it’s the same function name as the official function but it comes from the library.

That’s all there is! That’s how easy it is to use the library.

Curious how the library internally works?

The runAndroidComposeUiTest function is written by referencing its counterpart from the Jetpack’s official Compose test library.

In a nutshell, the runAndroidComposeUiTest utilizes AndroidComposeUiTestEnvironment to run the test and provide AndroidComposeUiTest to the trailing lambda(block) to perform assertions on composables. AndroidComposeUiTestEnvironment does not hold reference to the Activity; instead, it uses the ActivityScenario created by the parameter activityLauncher to retrieve the Activity instance whenever it needs.

The overloaded runAndroidComposeUiTest that takes in an intent uses the one that takes in activityLauncher internally, which is explained above.

As for createAndroidComposeTestRule, it initializes an instance of AndroidComposeTestRule using an ActivityScenarioRule created with the provided intent. It returns the initialized AndroidComposeTestRule instance, which is then available for use in performing assertions on composables.

The library hides all of these details from developers, allowing them to concentrate on writing the actual test cases.

If you find this article and the library valuable, a round of applause would be much appreciated. Please, feel free to leave a comment if anything needs clarification or if you have additional insights. Your feedback fuels my commitment to enhancing my blogging skills and supporting fellow developers.

I hope you enjoyed the article! Happy coding!

Source link