Skip to content

roman-kamyshnikov/automatic-screenshot-testing

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Automatic screenshot tests for Jetpack Compose @Preview

1) Overview

This repository demonstrates a zero-boilerplate way to generate screenshot tests for all your Jetpack Compose @Previews using JVM unit tests. It’s built on top of Now in Android and uses Paparazzi under the hood (no emulator required). It provider an easy to replicate pattern for broad UI coverage with minimal code.

2) Repository layout & points of interest

  • PreviewTests.kt — Discovers previews at runtime and runs Paparazzi snapshots for each.
  • core/ui/screenshottest — Tiny, focused utilities for test behaviour configuration:
    • IgnoreScreenshotTest.kt — Opt-out any preview from the sweep.
    • ScreenshotTestParameters.kt — Per-preview render configuration (e.g., NORMAL vs SHRINK).
    • NamedPreviewParameterProvider.kt — Preserves meaningful names for PreviewParameterProvider inputs.

3) How it works (high level)

  • Discovery via reflection: all functions annotated with @Preview are found at test time. Multi-preview annotations used in Now in Android (@DevicePreviews, @ThemePreviews) are treated as regular previews and included automatically.

  • Per-preview configuration: optional @ScreenshotTestParameters lets a preview adjust its Paparazzi rendering mode (defaults to SHRINK, can switch to NORMAL) without touching the test harness. This can easily be expanded to pass any additional configuration to the test that is required for a project.

  • Parameterized execution: a single JUnit test iterates all discovered previews and calls paparazzi.snapshot { ... } for each one.

  • Opt-out: add @IgnoreScreenshotTest on a preview to exclude it from the sweep.

  • No emulator / instrumentation: everything runs as a JVM unit test using Paparazzi, so it’s fast and stable.

4) Running the screenshot tests

Record snapshots (first run or when intentionally updating baselines): ./gradlew clean screenshot-test:recordPaparazziProdRelease

Verify snapshots (regular PR use): ./gradlew clean screenshot-test:verifyPaparazziProdRelease

  • Pass: no diffs vs recorded images.
  • Fail: visual diffs detected; re-record when changes are expected.

5) How to copy this into your project

  • What to copy

    • The test driver pattern from screenshot-test/.../PreviewTests.kt.
    • The helper annotations and utilities (if needed) from core/ui/.../screenshottest:
      • IgnoreScreenshotTest.kt
      • ScreenshotTestParameters.kt
      • NamedPreviewParameterProvider.kt
  • What to set up (Kotlin DSL)

    • Apply the Paparazzi Gradle plugin in your test module.
    • Add dependencies used by the approach: Paparazzi (JUnit rule), org.jetbrains.kotlin:kotlin-reflect, org.reflections:reflections (or ClassGraph), and com.google.testparameterinjector:test-parameter-injector.
    • Point the reflection scan to your app’s base package.
  • Project tweaks

    • Previews can be public or private. By default, both are handled and private previews are made accessible during discovery.
    • Adjust or remove multi-preview annotation detection. The example uses ThemePreviews and DevicePreviews from the Now in Android project.

6) Automation benefits

  • Coverage without ceremony: turns the previews you already maintain into screenshot tests automatically.
  • Deterministic & fast due to Paparazzi: runs as JVM tests, no emulator flakiness.
  • Low maintenance: a tiny test harness + a couple of lightweight annotations enable complete preview test coverage.
  • Scales with teams: new UI = new preview = new snapshot, with sensible naming and baselines.
  • Clear trade-offs: reflection adds a small discovery cost, but avoids per-screen boilerplate and keeps the codebase clean. Another downside is build times for test execution: even though Paparazzi does not require an emulater and tests are very fast, for very large codebases it might be sensible to split preview detection and test execution on a per-module basis for incremental builds & testing.

7) License

This project is licensed under Apache 2.0. See LICENSE for details.

About

Automatic screenshot testing for Jetpack Compose previews (Now in Android app fork)

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Languages

  • Kotlin 98.9%
  • Shell 1.1%