Waldo sessions now support scripting! – Learn more
App Development

Getting Started With Testing With Compose

Juan Reyes
Juan Reyes
Getting Started With Testing With Compose
January 31, 2023
7
min read

In recent years, Android development has shifted significantly toward declarative UI frameworks, with Jetpack Compose being the latest addition to the ecosystem. Declarative UI frameworks offer control structures that programmers may utilize to alter how the system draws the user interface. Declaratively created user interfaces can employ these control structures to be more dynamic than the imperative frameworks commonly used for Android and IOS development. 

In this article, we'll cover some of the best practices and techniques for testing Jetpack Compose–based apps and how you can use these tools and techniques to ensure the quality and reliability of your app. 

We'll start by explaining Jetpack and how the Compose framework works. Then we'll discuss unit testing and how to build a test workflow. Next, we'll explore how to do simple integration testing and Espresso testing with some examples. Finally, we'll enumerate the advantages and disadvantages of testing with Jetpack.

If this is your first time working with Android, check these articles before continuing. 

What Is Jetpack Compose?

Jetpack Compose is a modern, reactive UI framework for Android that allows developers to quickly and easily build beautiful, responsive, and customizable user interfaces. 

One of the key benefits is its ability to significantly reduce the amount of boilerplate code required to build UI elements. This makes it easier and faster for developers to build and maintain their apps as well as making it easier to test and debug them. 

However, testing with Jetpack Compose can still be challenging, especially for those new to the framework. 

Test Workflow With Compose and Unit Testing

Unit testing is a crucial component of any software development process, and it's no different with Jetpack Compose. Unit testing allows developers to test individual code units in isolation, ensuring that they work as intended and that any changes made to the code don't break existing functionality. 

Check out this article if you want to learn more about unit testing.

To unit test Jetpack Compose code, you can use the AndroidX Test library. It provides several valuable tools and classes for testing Android apps, including the ComposeTestRule class. 

The ComposeTestRule class is provided by the AndroidX Test library, which allows developers to create and manipulate Jetpack Compose views in their tests. It's designed to be used in conjunction with the JUnit 4 testing framework and can be used to set up and tear down Jetpack Compose views as part of a test workflow.

To use the ComposeTestRule, you'll need to annotate your test class with the @RunWith(JUnit4::class) annotation and create a ComposeTestRule instance as a @get:Rule field in your class. You can then use this instance to set the content of your Activity to a Jetpack Compose view and interact with this view as part of your test. 

Using ComposeTestRule

Here's an example of how you might use the ComposeTestRule class to test a simple Jetpack Compose UI element: 


@RunWith(JUnit4::class)
class MyTest {
  @get:Rule
  val composeTestRule = ComposeTestRule()

  @Test
  fun testMyButton() {
    // Create the Jetpack Compose view
    val myButton = @Composable {
      Button(onClick = { /* Do something */ }) {
        Text("Click me")
      }
    }

    // Set the view as the content of the Activity
    composeTestRule.setContent {
      myButton
    }

    // Find the Button view and perform a click action
    onNodeWithText("Click me").performClick()

    // Verify that the button was clicked
    assertTrue(/* Button was clicked */)
  }
}

In this example, we used the ComposeTestRule to set the Jetpack Compose view as the content of the Activity and then utilized the onNodeWithText() method to find the Button view and perform a click action on it. We can then use assertions to verify that the button was clicked as expected. 

Integration Testing

While unit testing is vital for testing individual units of code, it's also essential to test how these units work together as a whole. This is where integration testing comes in. 

Integration testing allows developers to test the integration of different code units, ensuring that they work together correctly and that any changes made to one unit don't break the functionality of another.

To perform integration testing with Jetpack Compose, you can use the AndroidJUnitRunner class, which is part of the AndroidX Test library. Much like a UI test workflow, this class allows you to launch an Activity and interact with it as if it were a real user, including clicking buttons, entering text into fields, and more. 

Here's an example of how you might use the AndroidJUnitRunner class to perform integration testing with Jetpack Compose: 


@RunWith(AndroidJUnit4::class)
@LargeTest
class MyIntegrationTest {
  @get:Rule
  val activityRule = ActivityTestRule(MyActivity::class.java)

  @Test
  fun testMyUI() {
    // Find the Button view and perform a click action
    onView(withId(R.id.my_button)).perform(click())

    // Find the TextView and verify that the text has been updated
    onView(withId(R.id.my_text_view)).check(matches(withText("Button clicked!")))
  }
}

Here we're using the ActivityTestRule to launch the MyActivity Activity and then utilizing the onView() method to find the Button view and perform a click action. We can then use the onView() method again to find the TextView and verify that the text has been updated as expected. 

Espresso Testing

In addition to the AndroidX Test library, developers can also use the Espresso testing framework to test Jetpack Compose–based apps. Espresso is a popular testing framework for Android that allows developers to write reliable, automated UI tests for their apps.

To use Espresso with Jetpack Compose, you must use the ViewInteraction class to interact with your UI elements. The ViewInteraction class allows you to perform actions on views and assert their state. 

Here's an example of how you might use Espresso to test a Jetpack Compose UI element: 


@RunWith(AndroidJUnit4::class)
class MyEspressoTest {
  @get:Rule
  val activityRule = ActivityTestRule(MyActivity::class.java)

  @Test
  fun testMyButton() {
    // Find the Button view and perform a click action
    onView(withId(R.id.my_button)).perform(click())

    // Find the TextView and verify that the text has been updated
    onView(withId(R.id.my_text_view)).check(matches(withText("Button clicked!")))
  }
}

As you can see, once again, we're using the onView() method to find the Button view and perform a click action on it and then using the onView() method again to find the TextView and verify that the text has been updated as expected. 

Advantages and Disadvantages of Testing With Jetpack Compose

There are many advantages to using Jetpack Compose to develop your applications and leveraging their testing tools to validate your work. However, it's crucial to remember that, much like any other technology, there are tradeoffs. 

Here are the advantages and disadvantages of using Jetpack Compose. 

Advantages

  • Jetpack Compose allows developers to significantly reduce the boilerplate code required to build UI elements, making it easier and faster to develop and maintain apps. This also makes testing and debugging these apps easier as there is less code to worry about.
  • The AndroidX Test library and the Espresso testing framework provide a wide range of tools and features for testing Jetpack Compose–based apps, including the ability to set up and manipulate views, perform actions on views, and make assertions about their state.
  • Jetpack Compose uses a reactive programming model, meaning UI elements are automatically updated in response to changes in the underlying data. This makes it easier to test Jetpack Compose–based apps as you can modify the data and verify that the UI updates as expected.

Disadvantages

  • Jetpack Compose is a relatively new framework, and as such there may be a learning curve for developers who aren't familiar with it. This could make testing with Jetpack Compose more challenging for those new to the framework.
  • Jetpack Compose uses a different programming model than traditional Android UI frameworks, such as the Android View system. This may require developers to adopt new techniques and approaches to testing, which could be problematic if they need to become more familiar with these concepts.
  • Jetpack Compose is still in active development and may be subject to changes and updates that could affect how it's tested. This could make it more difficult to maintain tests over time as developers may need to constantly update their testing strategies to keep up with these changes.

Despite these concerns, there are still many reasons to go with Jetpack Compose for your next project. And if you're concerned about the challenges of testing, you can always use more robust and comprehensive solutions for automated testing, like Waldo. Thanks to the complete toolkit Waldo offers for UI testing, your code will be secure and robust. In addition, it's easy to use, even for non-developers, since it doesn't require coding. 

Conclusion: Jetpack Compose Tests

Testing is an essential part of the software development process, and it's no different when it comes to Jetpack Compose. Using the tools and techniques discussed in this article, you can ensure the quality and reliability of your Jetpack Compose–based apps and make it easier to identify and fix any issues that may arise. 

Automated E2E tests for your mobile app

Waldo provides the best-in-class runtime for all your mobile testing needs.
Get true E2E testing in minutes, not months.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.