agentsclimarketplace

Snapshot testing

Skill almasumdev/awesome-mobile-testing-agent-skills/.github/skills/ui/snapshot-testing

Expert guidance on snapshot / golden image testing across mobile stacks — Paparazzi (Android), swift-snapshot-testing (iOS), golden_toolkit (Flutter), and RN snapshot tests. Use when asked to lock down UI visuals or catch unintended rendering regressions.From its SKILL.md

Install
npx -y skills add almasumdev/awesome-mobile-testing-agent-skills --skill snapshot-testing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.2 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it

Snapshot Testing

Instructions

Snapshot tests render a UI component to a file (image or serialized tree) and fail if the next render differs. They excel at catching unintended visual regressions. They fail badly when used as a substitute for logic tests or when goldens are mass-regenerated without review.

1. Host-Rendered vs Device-Rendered

Always prefer host-rendered snapshot libraries — they run on the JVM / host Swift / host Dart and produce deterministic images without emulator skew.

  • AndroidPaparazzi (JVM) or Roborazzi (Robolectric + rendering). Avoid screenshotting via instrumentation unless you need a true-device render for a specific bug.
  • iOSswift-snapshot-testing runs on simulator but can be pinned to a specific simulator model/OS to stay deterministic.
  • Flutterflutter test --update-goldens with matchesGoldenFile, optionally via golden_toolkit or alchemist for multi-config runs. Renders off-device on host.
  • React Nativereact-test-renderer + jest's toMatchSnapshot for serialized trees; for pixel images use @storybook/test-runner + Chromatic or react-native-owl (device-based, slower).

2. Android — Paparazzi (Compose)

class CheckoutButtonScreenshot {
    @get:Rule val paparazzi = Paparazzi(
        deviceConfig = DeviceConfig.PIXEL_5,
        theme = "android:Theme.Material.Light.NoActionBar",
    )

    @Test fun default() = paparazzi.snapshot {
        AppTheme { CheckoutButton(state = Idle, onClick = {}) }
    }

    @Test fun loading() = paparazzi.snapshot {
        AppTheme { CheckoutButton(state = Loading, onClick = {}) }
    }
}

Goldens land under src/test/snapshots/images/. Commit them. Review diffs as code.

3. iOS — swift-snapshot-testing

final class CheckoutButtonSnapshotTests: XCTestCase {
    func test_default_lightMode() {
        let view = CheckoutButtonView(state: .idle)
        assertSnapshot(of: view, as: .image(traits: .init(userInterfaceStyle: .light)))
    }

    func test_default_darkMode() {
        let view = CheckoutButtonView(state: .idle)
        assertSnapshot(of: view, as: .image(traits: .init(userInterfaceStyle: .dark)))
    }
}

Pin the simulator in CI (platform=iOS Simulator,name=iPhone 15,OS=17.5); different iOS versions render font metrics differently.

4. Flutter — goldens with golden_toolkit

void main() {
  testGoldens('CheckoutButton states', (tester) async {
    final builder = DeviceBuilder()
      ..overrideDevicesForAllScenarios(devices: [Device.phone])
      ..addScenario(widget: const CheckoutButton(state: ButtonState.idle),    name: 'idle')
      ..addScenario(widget: const CheckoutButton(state: ButtonState.loading), name: 'loading');
    await tester.pumpDeviceBuilder(builder);
    await screenMatchesGolden(tester, 'checkout_button_states');
  });
}

Run flutter test --update-goldens locally to regenerate. In CI, run without the flag and fail on diff.

5. React Native — Component Tree Snapshot

import { render } from '@testing-library/react-native';

test('CheckoutButton renders in idle state', () => {
  const { toJSON } = render(<CheckoutButton state="idle" />);
  expect(toJSON()).toMatchSnapshot();
});

Tree snapshots catch structural drift. For pixel-accurate RN visuals, use Storybook + Chromatic or an image-diff tool; toMatchSnapshot alone will not catch style regressions.

6. Determinism Rules

  • Pin the theme, locale, and density. Render both light and dark explicitly.
  • Pin fonts. Embed the app's fonts in the test configuration; never rely on a system font the CI image may update.
  • Freeze animation and time. Use pump() / waitForIdle() / explicit animation-skipping.
  • Avoid network and images. Inject a fake image loader that produces a deterministic placeholder.

7. Reviewing Golden Diffs

  • PRs that touch goldens must show the image diff in review (most CI UIs render PNGs).
  • Do not click "update all" without inspecting each diff.
  • If a platform upgrade (e.g., new iOS) changes many goldens, update them in a separate PR tagged chore(goldens) so logic changes do not hide behind visual churn.

8. What Snapshot Testing Does NOT Cover

  • Accessibility — use accessibility tests.
  • Behavior — a button can render correctly and still navigate nowhere.
  • Data correctness — a list can render beautifully with the wrong items.

9. Checklist

  • Snapshots run on host (JVM / simulator pinned / Dart VM / Node), not on arbitrary emulators.
  • Theme, locale, density, and fonts are pinned.
  • Animations and image loading are deterministic.
  • Goldens are committed and reviewed as code; no mass auto-approval.
  • Light and dark modes are both snapshotted.
  • Platform-upgrade golden churn lives in its own PR.
  • Snapshot tests complement, not replace, logic and accessibility tests.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,782. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.