Testing: Android Native Screenshot Testing Framework for Compose - devrath/RunTracer GitHub Wiki

Screenshot-Testing-A-Detailed-Guide

Refrences

Commands

Description Command
Generating Screenshots ./gradlew updateDebugScreenshotTest
Validating Screenshots ./gradlew validateDebugScreenshotTest

Steps to integrate

Step-1 - Add the dependencies in the version catalog

androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
screenshot = { id = "com.android.compose.screenshot", version.ref = "screenshot"}

Step-2 - Add the plugin and dependencies

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)
}

How to use it

Step-1 - We need to create a new package called screenshotTest

Screenshot 2024-07-06 at 9 22 09 PM

Step-2 - Now create a file called Previews.kt where we add all the previews of compose

Screenshot 2024-07-06 at 9 23 41 PM

Step-3 - Now our Previews.kt file looks like this for one preview example

@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-5 - Once the build generated is successful in the terminal, an indication is shown.

Screenshot 2024-07-06 at 9 27 19 PM

Step-6 - Snapshots are generated in debug [main] as shown in the image below

Screenshot 2024-07-06 at 9 31 00 PM

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

./gradlew validateDebugScreenshotTest

Step-8 - Now the results of the validation are seen in the location

Screenshot 2024-07-06 at 9 33 53 PM

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>

Advantages of Using Compose Native Testing in Android Kotlin Snapshot Testing

  1. Native Integration:

    • Advantage: Compose native testing integrates seamlessly with Jetpack Compose.
    • Benefit: Provides a more natural and idiomatic way to test Compose UI components.
  2. Live Updates:

    • Advantage: Allows testing of live updates and state changes within the Composables.
    • Benefit: Ensures that dynamic content and interactions are accurately tested.
  3. Granular Control:

    • Advantage: Offers fine-grained control over UI states and events.
    • Benefit: Enables thorough testing of different UI states and user interactions.
  4. 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.
  5. 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.
  6. Composable-Specific Assertions:

    • Advantage: Provides assertions specific to Compose UI components.
    • Benefit: Allows for more precise and meaningful assertions in tests.

Disadvantages of Using Compose Native Testing in Android Kotlin Snapshot Testing

  1. 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.
  2. Resource Intensive:

    • Disadvantage: Requires emulators or physical devices, which can be resource-intensive.
    • Impact: Increased complexity and cost for maintaining test infrastructure.
  3. 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.
  4. Complex Setup:

    • Disadvantage: Setting up and maintaining test environments can be complex.
    • Impact: Additional time and effort required for configuration and troubleshooting.
  5. 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.
  6. 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.

Conclusion

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.

⚠️ **GitHub.com Fallback** ⚠️