This repository is the official companion code for the article: "Clean Lap: UI Testing in Compose Multiplatform".
It serves as a practical implementation of a unified testing strategy, demonstrating how to write UI tests once in commonTest and execute them across Android, iOS, and Desktop targets.
This project showcases several advanced Compose Multiplatform concepts discussed in the article:
- Unified UI Testing: Leveraging the
ComposeUiTestAPI to run the same test suite across all supported platforms. - Asynchronous Testing: Implementing
waitUntiland semantic node polling to handleLaunchedEffectand Coroutine-driven state changes (seeFeedScreenTest.kt). - Shared Architecture: A clean, multiplatform implementation of
ViewModelandStateFlowusing Jetpack Lifecycle. - Navigation & State: A simple but effective screen switching mechanism (Home -> Login -> Feed) managed within the shared source set.
- Framework: Compose Multiplatform
- Architecture: Jetpack ViewModel (shared in
commonMain) - Testing: Compose UI Test API (v2)
- Concurrency: Kotlinx Coroutines
- Android Studio Koala (or newer)
- JDK 17
- Xcode (for iOS testing/running)
- Android: Run the
composeAppconfiguration. - Desktop: Execute
./gradlew :composeApp:run - iOS: Open
iosApp/iosApp.xcworkspacein Xcode.
The core value of this repository is the shared testing suite located in composeApp/src/commonTest.
./gradlew :composeApp:test./gradlew :composeApp:connectedDebugAndroidTest@Test
fun feedScreen_showsLoadingThenContent() = runComposeUiTest {
// ... initial loading state check ...
// Explicitly wait for the list to appear after async load
waitUntil(timeoutMillis = 1000) {
onAllNodesWithTag("feed_list").fetchSemanticsNodes().isNotEmpty()
}
}For the full breakdown of how this was built, read the complete article on KMP Bits.