snaptest 0.2.0
snaptest: ^0.2.0 copied to clipboard
Snap photos in your widget tests.
Snaptest #
See what your widgets look like during testing.
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
Recommended: Set up font loading #
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:
- Saves a beautiful screenshot with real rendering and device frames to
.snaptest/
- 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/framesSnaptestSettings.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.