[//]: # (title: Testing Compose Multiplatform UI)

UI testing in Compose Multiplatform is implemented using the same finders, assertions, actions, and matchers
as the Jetpack Compose testing API. If you're not familiar with them, read the [Jetpack Compose guide](https://developer.android.com/jetpack/compose/testing)
before you continue with this article.

> The API is [Experimental](supported-platforms.md#compose-multiplatform-ui-framework-stability-levels).
> It may change in the future.
>
{style="warning"}

## How Compose Multiplatform testing is different from Jetpack Compose

Compose Multiplatform common test API does not rely on JUnit's `TestRule` class. Instead, you call the `runComposeUiTest` function and invoke
the test functions on the `ComposeUiTest` receiver.

However, JUnit-based API is available for [desktop targets](compose-desktop-ui-testing.md).

## Writing and running tests with Compose Multiplatform

First, add the source set for tests and the necessary dependencies to the module. Then, write and run the example test
and try to customize it.

### Create the test source set and add the testing library to dependencies

To provide concrete examples, the instructions on this page follow the project structure generated by the
[Kotlin Multiplatform wizard](https://kmp.jetbrains.com/). If you are adding tests to an existing project, you may have
to replace `composeApp` in paths and commands with the module name you are testing (`shared`, for example).

Create a common test source set and add the necessary dependencies:

1. Create a directory for the common test source set: `composeApp/src/commonTest/kotlin`.
2. In the `composeApp/build.gradle.kts` file, add the following configuration:

    ```kotlin
    kotlin {
        //...
        sourceSets { 
            val jvmTest by getting
   
            // Adds common test dependencies
            commonTest.dependencies {
                implementation(kotlin("test"))
            
                @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
                implementation(compose.uiTest)
            }
   
            // Adds the desktop test dependency
            jvmTest.dependencies { 
                implementation(compose.desktop.currentOs)
            }
        }
    }
    ```

3. If you need to run instrumented (emulator) tests for Android, amend your Gradle configuration as follows:
   1. Add the following code to the `androidTarget {}` block to configure the instrumented test source set to depend on 
   a common test source set.

      ```kotlin
      kotlin {
          //...
          androidTarget { 
              @OptIn(ExperimentalKotlinGradlePluginApi::class)
              instrumentedTestVariant.sourceSetTree.set(KotlinSourceSetTree.test)
              //...
          }
          //... 
      }
      ```
   2. Follow the IDE's suggestions to add any missing imports.
   3. Add the following code to the `android.defaultConfig {}` block to configure the Android test instrumentation runner:

      ```kotlin
      android {
          //...
          defaultConfig {
              //...
              testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
          }
      }
      ```

   4. Add the required dependencies in the root `dependencies {}` block:

       ```kotlin
       dependencies { 
           androidTestImplementation("androidx.compose.ui:ui-test-junit4-android:%androidx.compose%")
           debugImplementation("androidx.compose.ui:ui-test-manifest:%androidx.compose%")
       }
       ```
4. Select **Build | Sync Project with Gradle Files** in the main menu, or click the Gradle refresh button in the
   build script editor.

Now, you are ready to write and run common tests for the Compose Multiplatform UI.

### Write and run common tests

In the `composeApp/src/commonTest/kotlin` directory, create a file named `ExampleTest.kt` and copy the following code into it:

```kotlin
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.runComposeUiTest
import kotlin.test.Test

class ExampleTest {

    @OptIn(ExperimentalTestApi::class)
    @Test
    fun myTest() = runComposeUiTest {
        // Declares a mock UI to demonstrate API calls
        //
        // Replace with your own declarations to test the code of your project
        setContent {
            var text by remember { mutableStateOf("Hello") }
            Text(
                text = text,
                modifier = Modifier.testTag("text")
            )
            Button(
                onClick = { text = "Compose" },
                modifier = Modifier.testTag("button")
            ) {
                Text("Click me")
            }
        }

        // Tests the declared UI with assertions and actions of the Compose Multiplatform testing API
        onNodeWithTag("text").assertTextEquals("Hello")
        onNodeWithTag("button").performClick()
        onNodeWithTag("text").assertTextEquals("Compose")
    }
}
```

To run tests:

<tabs>
<tab title="iOS Simulator">

You have two options:
* In Android Studio, you can click the green run icon in the gutter next to the `myTest()` function, choose
**Run | ExampleTest.myTest**, then select the iOS target for the test.
* Run the following command in the terminal:

   ```shell
   ./gradlew :composeApp:iosSimulatorArm64Test
   ```

</tab>
<tab title="Android Emulator">

Run this command in the terminal:

```shell
./gradlew :composeApp:connectedAndroidTest
```

Currently, you cannot run common Compose Multiplatform tests using `android (local)` test configurations, so gutter icons in
Android Studio, for example, won't be helpful.

</tab>
<tab title="Desktop">

You have two options:
* Click the green run icon in the gutter next to the `myTest()` function and choose **Run | ExampleTest.myTest**, then select the JVM target.
* Run the following command in the terminal:

   ```shell
   ./gradlew :composeApp:jvmTest
   ```

</tab>
<tab title="Wasm (headless browser)">

Run this command in the terminal:

```shell
./gradlew :composeApp:wasmJsTest
```

</tab>
</tabs>

## What's next

Now that you got the hang of Compose Multiplatform UI testing, you may want to check out more testing-related resources:
* For a general overview of testing in a Kotlin Multiplatform project, see [Understand basic project structure](multiplatform-discover-project.md#integration-with-tests)
and the [Test your multiplatform app](multiplatform-run-tests.md) tutorial.
* For details on setting up and running JUnit-based tests for desktop targets, see [](compose-desktop-ui-testing.md).
* For localization tests, see [](compose-localization-tests.md#testing-locales-on-different-platforms).
* More advanced testing in Android Studio, including automation, is covered in the [Test your app](https://developer.android.com/studio/test)
article in the Android Studio documentation.
