Skip to content

dfabulich/skipapp-compose-snapshot-sample

Repository files navigation

Skip Lite Compose Screenshot Testing Sample

This is a Skip Lite dual-platform app project, written mostly in Swift that transpiles to Kotlin, demonstrating how to setup and run Compose Preview Screenshot Testing.

What's Compose Preview Screenshot Testing?

In Compose Preview Screenshot Testing, you write @Preview components (like SwiftUI #Preview, but in Jetpack Compose) and decorate them with @PreviewTest. An update build plugin captures screenshots of all of your @PreviewTest components and writes them to disk; you commit them with your code.

Later, you run your tests again in validate mode. The tests fail if any of your components render differently. You then review the updated screenshots in a generate HTML report; if you approve of all of the changes, rerun update, which wil regenerate all of the snapshots.

Example screenshot

Writing a test

@PreviewTest
@Preview(showBackground = true)
@Composable
fun WelcomeViewPreview() {
    ProcessInfo.launch(LocalContext.current)
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colorScheme.background
    ) {
        WelcomeView(welcomeName = Binding.constant("Skipper"))
            .Compose(context = ComposeContext())
    }
}

Running tests

Generate screenshot test results:

gradle -p Android updateDebugScreenshotTest

Validate that screenshot test results are unchanged:

gradle -p Android validateDebugScreenshotTest

Setting up Compose Screenshot Testing from Scratch

The project was generated like this:

skip init --transpiled-app --appid=com.example.myapp skipapp-compose-snapshot-sample MyApp --no-build --free --git-repo

Then, I manually wired up Compose Preview Screenshot Testing. Skip's Gradle plugin generates a bunch of build.gradle.kts files, which makes wiring it up a little confusing.

Google's setup calls for four steps:

  1. Add android.experimental.enableScreenshotTest=true to gradle.properties.
  2. Add the following three settings to your module-level build.gradle.kts file
    • Add experimentalProperties["android.experimental.enableScreenshotTest"] = true to the android block of your module-level build.gradle.kts file, e.g. Android/app/build.gradle.kts.
    • Add the com.android.compose.screenshot plugin to the module-level app/build.gradle.kts.
    • Add the screenshot-validation-api and ui-tooling dependencies.

We need to follow those steps, but we also need to apply these settings to Skip's autogenerated Gradle projects. We do that in skip.yml, like this:

```yaml
build:
  contents:
    # Add the screenshot testing plugin
    - block: 'plugins'
      contents:
        - 'id("com.android.compose.screenshot") version "0.0.1-alpha13"'
    
    # Add screenshot testing dependencies
    - block: 'dependencies'
      contents:
        - 'screenshotTestImplementation("com.android.tools.screenshot:screenshot-validation-api:0.0.1-alpha13")'
        - 'screenshotTestImplementation("androidx.compose.ui:ui-tooling")'

    - block: 'android'
      contents:
        - 'experimentalProperties["android.experimental.enableScreenshotTest"] = true'

# Custom gradle properties
gradleProperties:
  android.experimental.enableScreenshotTest: "true"
```

Lastly, we can't test views marked internal, so we updated a view we wanted to test and marked it public (with a public var body: some View implementation).

Building

This project is both a stand-alone Swift Package Manager module, as well as an Xcode project that builds and translates the project into a Kotlin Gradle project for Android using the skipstone plugin.

Building the module requires that Skip be installed using Homebrew with brew install skiptools/skip/skip.

This will also install the necessary Skip prerequisites: Kotlin, Gradle, and the Android build tools.

Installation prerequisites can be confirmed by running skip checkup. The project can be validated with skip verify.

Running

Xcode and Android Studio must be downloaded and installed in order to run the app in the iOS simulator / Android emulator. An Android emulator must already be running, which can be launched from Android Studio's Device Manager.

The project can be opened and run in Xcode from Project.xcworkspace, which also enabled parallel development of any Skip libary dependencies.

To run both the Swift and Kotlin apps simultaneously, launch the "MyApp App" target from Xcode. A build phases runs the "Launch Android APK" script that will deploy the Skip app to a running Android emulator or connected device. Logging output for the iOS app can be viewed in the Xcode console, and in Android Studio's logcat tab for the transpiled Kotlin app, or using adb logcat from a terminal.

Testing

The module can be tested using the standard swift test command or by running the test target for the macOS destination in Xcode, which will run the Swift tests as well as the transpiled Kotlin JUnit tests in the Robolectric Android simulation environment.

Parity testing can be performed with skip test, which will output a table of the test results for both platforms.

License

This software is licensed under the GNU General Public License v2.0 or later.

About

Skip Lite Compose Screenshot Testing Sample

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors