runComposeUiTest

Function
Common
@ExperimentalTestApi
expect fun runComposeUiTest(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    runTestContext: CoroutineContext = EmptyCoroutineContext,
    testTimeout: Duration = 60.seconds,
    block: suspend ComposeUiTest.() -> Unit,
): TestResult

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 implementation uses kotlinx.coroutines.test.StandardTestDispatcher by default for running composition. 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.

Parameters

effectContext 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 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 The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.
block The test function.
Common
Deprecated Use androidx.compose.ui.test.v2.runComposeUiTest instead. The v2 APIs align with standard coroutine behavior by queuing tasks rather than executing them immediately. Tests relying on immediate execution may require explicit synchronization. Please refer to the migration guide for more details.
@ExperimentalTestApi
expect fun runComposeUiTest(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    runTestContext: CoroutineContext = EmptyCoroutineContext,
    testTimeout: Duration = 60.seconds,
    block: suspend ComposeUiTest.() -> Unit,
): TestResult

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.

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

Parameters

effectContext 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 or TestCoroutineScheduler (in that order), it will be used for composition and the MainTestClock.
runTestContext 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 The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.
block The test function.
Android
Deprecated Use androidx.compose.ui.test.v2.runComposeUiTest instead. The v2 APIs align with standard coroutine behavior by queuing tasks rather than executing them immediately. Tests relying on immediate execution may require explicit synchronization. Please refer to the migration guide for more details.
@ExperimentalTestApi
actual fun runComposeUiTest(
    effectContext: CoroutineContext,
    runTestContext: CoroutineContext,
    testTimeout: Duration,
    block: suspend ComposeUiTest.() -> Unit,
): TestResult

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.

Keeping a reference to the ComposeUiTest outside of this function is an error. Also avoid using androidx.compose.ui.test.junit4.ComposeTestRule (e.g., createComposeRule) inside runComposeUiTest or any of their respective variants. Since these APIs independently manage the test environment, mixing them may lead to unexpected behavior.

Parameters

effectContext 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 or TestCoroutineScheduler (in that order), it will be used for composition and the MainTestClock.
runTestContext 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 The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.
block The suspendable test body.
Android
@ExperimentalTestApi
actual fun runComposeUiTest(
    effectContext: CoroutineContext,
    runTestContext: CoroutineContext,
    testTimeout: Duration,
    block: suspend ComposeUiTest.() -> Unit,
): TestResult

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 implementation uses kotlinx.coroutines.test.StandardTestDispatcher by default for running composition. 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. Also avoid using androidx.compose.ui.test.junit4.ComposeTestRule (e.g., createComposeRule) inside runComposeUiTest or any of their respective variants. Since these APIs independently manage the test environment, mixing them may lead to unexpected behavior.

Parameters

effectContext 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 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 The Duration within which the test is expected to complete, otherwise a platform specific timeout exception will be thrown.
block The suspendable test body.

Code Examples

RunComposeUiTestSample

@OptIn(ExperimentalTestApi::class)
fun RunComposeUiTestSample() = 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"))
}