androidx.compose.ui.test.v2

Top-level functions summary

inline AndroidComposeUiTestEnvironment<A>
@ExperimentalTestApi
<A : ComponentActivity> AndroidComposeUiTestEnvironment(
    effectContext: CoroutineContext,
    runTestContext: CoroutineContext,
    testTimeout: Duration,
    crossinline activityProvider: () -> A?
)

Creates an AndroidComposeUiTestEnvironment that retrieves the host Activity by delegating to the given activityProvider.

android
inline Unit
@ExperimentalTestApi
<A : ComponentActivity> runAndroidComposeUiTest(
    effectContext: CoroutineContext,
    runTestContext: CoroutineContext,
    testTimeout: Duration,
    noinline block: suspend AndroidComposeUiTest<A>.() -> Unit
)

Variant of runComposeUiTest that allows you to specify which Activity should be launched.

android
Unit
@ExperimentalTestApi
<A : ComponentActivity> runAndroidComposeUiTest(
    activityClass: Class<A>,
    effectContext: CoroutineContext,
    runTestContext: CoroutineContext,
    testTimeout: Duration,
    block: suspend AndroidComposeUiTest<A>.() -> Unit
)

Variant of runComposeUiTest that allows you to specify which Activity should be launched.

android
<Error class: unknown class>
@ExperimentalTestApi
runComposeUiTest(
    effectContext: CoroutineContext,
    runTestContext: CoroutineContext,
    testTimeout: Duration,
    block: suspend ComposeUiTest.() -> Unit
)

Sets up the test environment, runs the given test and then tears down the test environment.

Cmn
android
Unit

Variant of runComposeUiTest that does not launch an Activity to host Compose content in and thus acts as an "empty shell".

android

Top-level functions

AndroidComposeUiTestEnvironment

@ExperimentalTestApi
inline fun <A : ComponentActivity> AndroidComposeUiTestEnvironment(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    runTestContext: CoroutineContext = EmptyCoroutineContext,
    testTimeout: Duration = 60.seconds,
    crossinline activityProvider: () -> A?
): AndroidComposeUiTestEnvironment<A>

Creates an AndroidComposeUiTestEnvironment that retrieves the host Activity by delegating to the given activityProvider. Use this if you need to launch an Activity in a way that is not compatible with any of the existing runComposeUiTest, runAndroidComposeUiTest, or runEmptyComposeUiTest methods.

This API differs from the deprecated API by using kotlinx.coroutines.test.StandardTestDispatcher by default for running composition, instead of kotlinx.coroutines.test.UnconfinedTestDispatcher. This ensures that the test behavior is consistent with kotlinx.coroutines.test.runTest and provides explicit control over coroutine execution order. This means you may need to explicitly advance time or run current coroutines when testing complex coroutine logic, as tasks are queued on the scheduler rather than running eagerly.

Valid use cases include, but are not limited to, creating your own JUnit test rule that implements AndroidComposeUiTest by delegating to androidx.compose.ui.test.AndroidComposeUiTestEnvironment.test. See AndroidComposeTestRule for a reference implementation.

The activityProvider is called every time activity is called, which in turn is called when setContent is called.

The most common implementation of an activityProvider retrieves the activity from a backing ActivityScenario (that the caller launches within the lambda passed to runTest), but one is not limited to this pattern.

Parameters
<A : ComponentActivity>

The Activity type to be interacted with, which typically (but not necessarily) is the activity that was launched and hosts the Compose content.

effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher, it is used for composition and the MainTestClock. Otherwise, a kotlinx.coroutines.test.StandardTestDispatcher is created and used. This new dispatcher will share the TestCoroutineScheduler from effectContext if one is present.

runTestContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to create the context to run the test. By default it will run using kotlinx.coroutines.test.StandardTestDispatcher. runTestContext and effectContext must not share TestCoroutineScheduler.

testTimeout: Duration = 60.seconds

The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.

crossinline activityProvider: () -> A?

A lambda that should return the current Activity instance of type A, if it is available. If it is not available, it should return null.

runAndroidComposeUiTest

@ExperimentalTestApi
inline fun <A : ComponentActivity> runAndroidComposeUiTest(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    runTestContext: CoroutineContext = EmptyCoroutineContext,
    testTimeout: Duration = 60.seconds,
    noinline block: suspend AndroidComposeUiTest<A>.() -> Unit
): Unit

Variant of runComposeUiTest that allows you to specify which Activity should be launched. Be aware that if the Activity sets content during its launch, you cannot use setContent on the ComposeUiTest anymore as this would override the content and can lead to subtle bugs.

This API differs from the deprecated API by using kotlinx.coroutines.test.StandardTestDispatcher by default for running composition, instead of kotlinx.coroutines.test.UnconfinedTestDispatcher. This ensures that the test behavior is consistent with kotlinx.coroutines.test.runTest and provides explicit control over coroutine execution order. This means you may need to explicitly advance time or run current coroutines when testing complex coroutine logic, as tasks are queued on the scheduler rather than running eagerly.

Parameters
<A : ComponentActivity>

The Activity type to be launched, which typically (but not necessarily) hosts the Compose content

effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher, it is used for composition and the MainTestClock. Otherwise, a kotlinx.coroutines.test.StandardTestDispatcher is created and used. This new dispatcher will share the TestCoroutineScheduler from effectContext if one is present.

runTestContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to create the context to run the test block. By default block will run using kotlinx.coroutines.test.StandardTestDispatcher. runTestContext and effectContext must not share TestCoroutineScheduler.

testTimeout: Duration = 60.seconds

The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.

noinline block: suspend AndroidComposeUiTest<A>.() -> Unit

The test function.

runAndroidComposeUiTest

@ExperimentalTestApi
fun <A : ComponentActivity> runAndroidComposeUiTest(
    activityClass: Class<A>,
    effectContext: CoroutineContext = EmptyCoroutineContext,
    runTestContext: CoroutineContext = EmptyCoroutineContext,
    testTimeout: Duration = 60.seconds,
    block: suspend AndroidComposeUiTest<A>.() -> Unit
): Unit

Variant of runComposeUiTest that allows you to specify which Activity should be launched. Be aware that if the Activity sets content during its launch, you cannot use setContent on the ComposeUiTest anymore as this would override the content and can lead to subtle bugs.

This API differs from the deprecated API by using kotlinx.coroutines.test.StandardTestDispatcher by default for running composition, instead of kotlinx.coroutines.test.UnconfinedTestDispatcher. This ensures that the test behavior is consistent with kotlinx.coroutines.test.runTest and provides explicit control over coroutine execution order. This means you may need to explicitly advance time or run current coroutines when testing complex coroutine logic, as tasks are queued on the scheduler rather than running eagerly.

Parameters
<A : ComponentActivity>

The Activity type to be launched, which typically (but not necessarily) hosts the Compose content

activityClass: Class<A>

The Class of the Activity type to be launched, corresponding to A.

effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher, it is used for composition and the MainTestClock. Otherwise, a kotlinx.coroutines.test.StandardTestDispatcher is created and used. This new dispatcher will share the TestCoroutineScheduler from effectContext if one is present.

runTestContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to create the context to run the test block. By default block will run using kotlinx.coroutines.test.StandardTestDispatcher. runTestContext and effectContext must not share TestCoroutineScheduler.

testTimeout: Duration = 60.seconds

The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.

block: suspend AndroidComposeUiTest<A>.() -> Unit

The test function.

runComposeUiTest

@ExperimentalTestApi
fun runComposeUiTest(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    runTestContext: CoroutineContext = EmptyCoroutineContext,
    testTimeout: Duration = 60.seconds,
    block: suspend ComposeUiTest.() -> Unit
): <Error class: unknown class>

Sets up the test environment, runs the given test and then tears down the test environment. Use the methods on ComposeUiTest in the test to find Compose content and make assertions on it. If you need access to platform specific elements (such as the Activity on Android), use one of the platform specific variants of this method, e.g. runAndroidComposeUiTest on Android.

Implementations of this method will launch a Compose host (such as an Activity on Android) for you. If your test needs to launch its own host, use a platform specific variant that doesn't launch anything for you (if available), e.g. runEmptyComposeUiTest on Android. Always make sure that the Compose content is set during execution of the test lambda so the test framework is aware of the content. Whether you need to launch the host from within the test lambda as well depends on the platform.

This API differs from the deprecated API by using kotlinx.coroutines.test.StandardTestDispatcher by default for running composition, instead of kotlinx.coroutines.test.UnconfinedTestDispatcher. This ensures that the test behavior is consistent with kotlinx.coroutines.test.runTest and provides explicit control over coroutine execution order. This means you may need to explicitly advance time or run current coroutines when testing complex coroutine logic, as tasks are queued on the scheduler rather than running eagerly.

Keeping a reference to the ComposeUiTest outside of this function is an error.

import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.v2.runComposeUiTest

runComposeUiTest {
    var counter by mutableIntStateOf(1)
    setContent {
        Column {
            Text(text = "Count: $counter", modifier = Modifier.testTag("text_tag"))
            Button(onClick = { counter++ }, modifier = Modifier.testTag("button_tag")) {
                Text("Click Me!")
            }
        }
    }

    onNodeWithTag("button_tag").performClick()
    onNodeWithTag("text_tag").assert(hasText("Count: 2"))
}
Parameters
effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher, it is used for composition and the MainTestClock. Otherwise, a kotlinx.coroutines.test.StandardTestDispatcher is created and used. This new dispatcher will share the TestCoroutineScheduler from effectContext if one is present.

runTestContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to create the context to run the test block. By default block will run using kotlinx.coroutines.test.StandardTestDispatcher. runTestContext and effectContext must not share TestCoroutineScheduler.

testTimeout: Duration = 60.seconds

The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.

block: suspend ComposeUiTest.() -> Unit

The test function.

runEmptyComposeUiTest

@ExperimentalTestApi
fun runEmptyComposeUiTest(block: ComposeUiTest.() -> Unit): Unit

Variant of runComposeUiTest that does not launch an Activity to host Compose content in and thus acts as an "empty shell". Use this if you need to have control over the timing and method of launching the Activity, for example when you want to launch it with a custom Intent, or if you have a complex test setup.

This API differs from the deprecated API by using kotlinx.coroutines.test.StandardTestDispatcher by default for running composition, instead of kotlinx.coroutines.test.UnconfinedTestDispatcher. This ensures that the test behavior is consistent with kotlinx.coroutines.test.runTest and provides explicit control over coroutine execution order. This means you may need to explicitly advance time or run current coroutines when testing complex coroutine logic, as tasks are queued on the scheduler rather than running eagerly.

When using this method, calling ComposeUiTest.setContent will throw an IllegalStateException. Instead, you'll have to set the content in the Activity that you have launched yourself, either directly on the Activity or on an androidx.compose.ui.platform.AbstractComposeView. You will need to do this from within the test lambda, or the test framework will not be able to find the content.