这是indexloc提供的服务,不要输入任何密码

snaptest 0.2.0 copy "snaptest: ^0.2.0" to clipboard
snaptest: ^0.2.0 copied to clipboard

Snap photos in your widget tests.

Snaptest #

Code Coverage melos lints by lintervention

See what your widgets look like during testing.

Title banner

Snaptest is simple: call snap() in any widget test to save a screenshot of what's currently on screen. Perfect for debugging, documentation, and visual regression testing.

Installation #

dart pub add dev:snaptest

Create a flutter_test_config.dart file in your test/ directory to ensure consistent font rendering:

import 'dart:async';
import 'package:snaptest/snaptest.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  // Load fonts before all tests to prevent side effects
  await loadFontsAndIcons();

  // Optional: Set global settings for all tests
  SnaptestSettings.global = SnaptestSettings(
    devices: [
      Devices.ios.iPhone16Pro,
    ],
  );

  await testMain();
}

Why this matters: Flutter can't unload fonts once loaded, so without this setup, your snap() calls might influence your test layout later and produce different results depending on test execution order.

The Basics 🚀 #

Just call snap() to see your screen #

Add one line to any widget test to see what it looks like:

import 'package:flutter_test/flutter_test.dart';
import 'package:snaptest/snaptest.dart';

testWidgets('My widget test', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: MyPage()));
  
  // That's it! Screenshot saved to .snaptest/
  await snap();
});

The screenshot gets saved as a PNG file in .snaptest/ using your test name. Great for debugging failing tests or documenting what your widgets actually look like.

Configure your .gitignore #

**/.snaptest/     # Screenshots (usually not committed)

Level Up: Real Rendering 📱 #

By default, snaptest creates simplified screenshots (blocked text, no images/shadows) for consistency. But you can enable real rendering to see exactly what users see:

testWidgets('Real rendering example', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: MyPage()));
  
  await snap(
    settings: SnaptestSettings.rendered([
      Devices.ios.iPhone16Pro,
      Devices.android.samsungGalaxyS20,
    ]),
  );
});

This creates beautiful screenshots with:

  • ✅ Real text rendering
  • ✅ Actual images
  • ✅ Shadows and effects
  • ✅ Device frames around the content
  • ✅ Multiple device sizes
  • ✅ Multiple orientations (portrait and landscape)

Perfect for documentation, design reviews, or showing stakeholders what the app actually looks like.

Level Up: Golden File Testing 🎯 #

Want automated visual regression testing? Enable golden comparison to catch unintended UI changes:

testWidgets('Golden comparison test', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: LoginScreen()));
  
  await snap(
    matchToGolden: true,
    settings: SnaptestSettings.rendered([Devices.ios.iPhone16Pro]),
  );
});

This does both:

  1. Saves a beautiful screenshot with real rendering and device frames to .snaptest/
  2. Compares against golden files to fail the test if UI changes unexpectedly

When golden tests fail due to intentional changes, update them:

flutter test --update-goldens

All the Options 🛠️ #

Multiple screenshots per test #

testWidgets('User flow', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: MyPage()));
  await snap('initial_state');
  
  await tester.tap(find.byType(FloatingActionButton));
  await tester.pumpAndSettle();
  await snap('after_tap');
});

Capture specific widgets #

await snap(from: find.byKey(const Key('my-card')));

Global settings for all tests #

void main() {
  setUpAll(() {
    SnaptestSettings.global = SnaptestSettings.rendered([
      Devices.ios.iPhone16Pro,
    ]);
  });
  
  // All snap() calls now use iPhone 16 Pro with real rendering
}

Or create a flutter_test_config.dart file to set the global settings, as described in the Installation section.

Dedicated screenshot tests with snapTest #

For tests specifically designed for screenshots, use snapTest instead of testWidgets. It automatically:

  • Adds the snaptest tag for easy filtering
  • Applies custom settings for the entire test
import 'package:flutter/material.dart';
import 'package:snaptest/snaptest.dart';

snapTest('Login screen looks correct', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: LoginScreen()));
  await snap(); // Uses the settings from snapTest
});

snapTest(
  'Multi-device homepage',
  (tester) async {
    await tester.pumpWidget(const MaterialApp(home: HomePage()));
    await snap('initial');
    
    await tester.tap(find.byIcon(Icons.menu));
    await tester.pumpAndSettle();
    await snap('menu_open');
  },
  settings: SnaptestSettings.rendered([
    Devices.ios.iPhone16Pro,
    Devices.android.samsungGalaxyS20,
  ]),
);

Run only screenshot tests:

flutter test --tags snaptest

Or exclude them from regular test runs:

flutter test --exclude-tags snaptest

Test multiple orientations #

testWidgets('Responsive design test', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: MyPage()));
  
  await snap(
    settings: SnaptestSettings.rendered(
      devices: [Devices.ios.iPhone16Pro],
      orientations: {
        Orientation.portrait,
        Orientation.landscape,
      },
    ),
  );
});

This automatically creates separate screenshots for each orientation:

  • my_page_iPhone16Pro_portrait.png
  • my_page_iPhone16Pro_landscape.png

All snap() parameters #

await snap(
  name: 'custom_name',           // Custom filename
  from: find.byKey(key),         // Specific widget to capture
  settings: SnaptestSettings(),  // Override global settings
  goldenPrefix: 'goldens/',      // Golden files directory (default: 'goldens/')
  matchToGolden: true,           // Enable golden file comparison
);

Settings Reference 📋 #

SnaptestSettings options: #

  • devices: List of devices to test on (default: [WidgetTesterDevice()])
  • orientations: Set of orientations to test (default: {Orientation.portrait})
  • blockText: Whether to block text rendering for consistency (default: true)
  • renderImages: Whether to render actual images (default: false)
  • renderShadows: Whether to render shadows (default: false)
  • includeDeviceFrame: Whether to include device frame around content (default: false)
  • pathPrefix: Directory where screenshots are saved (default: '.snaptest/')

Convenience constructors: #

  • SnaptestSettings(): Default settings - blocked text, no images/shadows/frames
  • SnaptestSettings.rendered(devices): Real rendering - actual text, images, shadows, and device frames

Helper Scripts 🔧 #

Clean all screenshots:

dart run snaptest:clean

Clean screenshots from a custom directory:

dart run snaptest:clean my_custom_dir

Assemble screenshots into a single directory:

dart run snaptest:assemble

Assemble screenshots from a custom directory:

dart run snaptest:assemble my_custom_dir

Custom Screenshot Directories #

You can customize where screenshots are saved by setting the pathPrefix in your settings:

testWidgets('Custom directory example', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: MyPage()));
  
  await snap(
    settings: SnaptestSettings(
      pathPrefix: 'my_screenshots/',
      // ... other settings
    ),
  );
});

The helper scripts will work with any custom directory name you specify.

Font Limitations ⚠️ #

Due to Flutter's test environment limitations:

  • iOS system fonts are replaced with Roboto for consistency
  • Google Fonts only work if bundled as local assets (not fetched remotely)
  • Custom fonts must be included in your pubspec.yaml

This ensures consistent screenshots across environments, but may differ slightly from your actual app.