Testing: Android Native Screenshot Testing Framework for Compose - devrath/RunTracer GitHub Wiki
Description | Command |
---|---|
Generating Screenshots | ./gradlew updateDebugScreenshotTest |
Validating Screenshots | ./gradlew validateDebugScreenshotTest |
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
screenshot = { id = "com.android.compose.screenshot", version.ref = "screenshot"}
plugins {
alias(libs.plugins.screenshot)
}
android {
namespace = "com.istudio.core.presentation.designsystem"
// Remove once screenshot api is stable
experimentalProperties["android.experimental.enableScreenshotTest"] = true
}
dependencies {
debugImplementation(libs.androidx.ui.tooling)
// For screenshot testing
screenshotTestImplementation(libs.androidx.ui.tooling)
}


@file:OptIn(ExperimentalFoundationApi::class)
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text2.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.istudio.core.presentation.designsystem.RunTracerTheme
import com.istudio.core.presentation.designsystem.components.RunTracerPasswordTextField
import com.istudio.core.presentation.designsystem.preview.WindowSizeClassPreviews
@Preview
@Composable
private fun RunTracerTextFieldPreview() {
RunTracerTheme {
RunTracerPasswordTextField(
state = rememberTextFieldState(),
hint = "[email protected]",
title = "Email",
modifier = Modifier.fillMaxWidth(),
isPasswordVisible = false,
onTogglePasswordVisibility = {}
)
}
}
Step-4
- We need to generate snapshots when we build the UI, This sets the baseline snapshot and this has to be done only once using the command
./gradlew updateDebugScreenshotTest


Step-7
- Now run the command to validate that the baseline snapshot is the same as the latest UI with
./gradlew validateDebugScreenshotTest

Step-9
- Contents of the generated validation result are below, You can see how many successes and failures and skipped results are there.
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="PreviewsKt" tests="1" skipped="0" failures="0" errors="0" timestamp="2024-07-06T16:02:39" hostname="GU-KC9PPH6RLL.local" time="0.064">
<properties/>
<testcase name="RunTracerTextFieldPreview" classname="PreviewsKt" time="0.064"/>
<system-out><![CDATA[]]></system-out>
<system-err><![CDATA[]]></system-err>
</testsuite>
-
Native Integration:
- Advantage: Compose native testing integrates seamlessly with Jetpack Compose.
- Benefit: Provides a more natural and idiomatic way to test Compose UI components.
-
Live Updates:
- Advantage: Allows testing of live updates and state changes within the Composables.
- Benefit: Ensures that dynamic content and interactions are accurately tested.
-
Granular Control:
- Advantage: Offers fine-grained control over UI states and events.
- Benefit: Enables thorough testing of different UI states and user interactions.
-
Composable Preview:
-
Advantage: Supports the
@Preview
annotation for testing UI directly in the IDE. - Benefit: Facilitates quick visual verification of UI components without running the full application.
-
Advantage: Supports the
-
Unified Development and Testing:
- Advantage: Uses the same language and tools for both development and testing.
- Benefit: Simplifies the learning curve and improves developer productivity.
-
Composable-Specific Assertions:
- Advantage: Provides assertions specific to Compose UI components.
- Benefit: Allows for more precise and meaningful assertions in tests.
-
Performance Overhead:
- Disadvantage: Running tests in an emulator or on a physical device can be slower compared to JVM-based testing.
- Impact: Longer feedback loop for developers compared to tools like Paparazzi.
-
Resource Intensive:
- Disadvantage: Requires emulators or physical devices, which can be resource-intensive.
- Impact: Increased complexity and cost for maintaining test infrastructure.
-
Flakiness:
- Disadvantage: Tests can be flaky due to various factors like emulator/device performance and environmental differences.
- Impact: May lead to unreliable test results and increased maintenance effort.
-
Complex Setup:
- Disadvantage: Setting up and maintaining test environments can be complex.
- Impact: Additional time and effort required for configuration and troubleshooting.
-
Dependency on Android Framework:
- Disadvantage: Tests are dependent on the Android framework and its lifecycle.
- Impact: Makes tests less portable and harder to run outside the Android environment.
-
Limited to Compose:
- Disadvantage: Only applicable to projects using Jetpack Compose.
- Impact: Not suitable for projects that still use XML-based layouts or hybrid projects.
Compose native testing in Android Kotlin provides a powerful and integrated approach to testing Jetpack Compose UI components. It offers advantages in terms of native integration, live updates, and granular control over UI states. However, it also comes with challenges related to performance, resource requirements, and setup complexity. Balancing these factors is essential for effectively using Compose native testing in your snapshot testing strategy.