Golden File Testing
The term golden file refers to a master image that is considered the true rendering of a given widget, state, application, or other visual representation you have chosen to capture.
Golden tests help catch unintended visual regressions early, ensuring that your UI looks exactly the way you expect across changes. We recommend using Alchemist for golden file testing because it provides a declarative API, handles cross-platform rendering inconsistencies, and makes it straightforward to test multiple widget states in a single test file.
Setting up Alchemist
Section titled “Setting up Alchemist”Add Alchemist as a dev dependency:
dart pub add dev:alchemistConfigure flutter_test_config.dart
Section titled “Configure flutter_test_config.dart”Create a flutter_test_config.dart file at the root of your test/ directory to configure Alchemist for your project. This file runs before every test file and lets you set a shared theme and control platform-specific behavior:
import 'dart:async';
import 'package:alchemist/alchemist.dart';
Future<void> testExecutable(FutureOr<void> Function() testMain) async { const isRunningInCi = bool.fromEnvironment('CI');
return AlchemistConfig.runWithConfig( config: AlchemistConfig( platformGoldensConfig: PlatformGoldensConfig( enabled: !isRunningInCi, ), ), run: testMain, );}This setup disables platform-specific golden tests in CI, where rendering differences across operating systems can cause false failures. Only CI-safe goldens (which replace text with colored blocks) run in CI, keeping your pipeline stable.
Directory structure for golden files
Section titled “Directory structure for golden files”Alchemist generates golden images in a goldens/ directory next to your test files. We recommend tracking only the CI goldens in version control, since platform goldens vary across operating systems:
test/├── flutter_test_config.dart├── goldens/│ ├── ci/ # Tracked in version control│ ├── macos/ # Platform-specific, not tracked│ └── linux/ # Platform-specific, not tracked└── my_widget_golden_test.dartAdd the following to your .gitignore:
test/**/goldens/**/*.*!test/**/goldens/ci/*.*Writing golden tests with Alchemist
Section titled “Writing golden tests with Alchemist”Use goldenTest along with GoldenTestGroup and GoldenTestScenario to declare your golden tests. This approach groups multiple widget states into a single golden image, making it easy to review visual changes at a glance.
import 'package:alchemist/alchemist.dart';import 'package:flutter/material.dart';
void main() { goldenTest( 'renders correctly', fileName: 'my_button', builder: () => GoldenTestGroup( children: [ GoldenTestScenario( name: 'default', child: const MyButton(label: 'Click me'), ), GoldenTestScenario( name: 'disabled', child: const MyButton(label: 'Click me', enabled: false), ), ], ), );}import 'package:flutter_test/flutter_test.dart';
void main() { // Separate test for every state is harder to review // and more susceptible to cross-platform rendering differences. testWidgets('renders default state', (tester) async { await tester.pumpWidget(const MyButton(label: 'Click me')); await expectLater( find.byType(MyButton), matchesGoldenFile('my_button_default.png'), ); });
testWidgets('renders disabled state', (tester) async { await tester.pumpWidget( const MyButton(label: 'Click me', enabled: false), ); await expectLater( find.byType(MyButton), matchesGoldenFile('my_button_disabled.png'), ); });}Simulating interactions before capture
Section titled “Simulating interactions before capture”Alchemist supports performing gestures or other setup before the golden image is captured. Use the whilePerforming parameter to simulate interactions like presses, long presses, or scrolls:
goldenTest( 'renders pressed state', fileName: 'my_button_pressed', whilePerforming: press(find.byType(MyButton)), builder: () => GoldenTestGroup( children: [ GoldenTestScenario( name: 'pressed', child: const MyButton(label: 'Click me'), ), ], ),);Tag golden tests
Section titled “Tag golden tests”Golden tests should be tagged to make it easier to run them separately from other tests.
goldenTest( 'renders correctly', fileName: 'my_widget', builder: () => GoldenTestGroup( children: [ GoldenTestScenario( name: 'default', child: const MyWidget(), ), ], ),);goldenTest( 'renders correctly', fileName: 'my_widget', builder: () => GoldenTestGroup( children: [ GoldenTestScenario( name: 'default', child: const MyWidget(), ), ], ),);Configure your golden test tag
Section titled “Configure your golden test tag”To configure a golden test tag across multiple files (or an entire package), create a dart_test.yaml file and add the tag configuration:
tags: golden: description: "Tests that compare golden files."You can then run the tests with the tag golden in isolation, or quickly update
the golden files with the --update-goldens flag:
flutter test --tags golden # Run only golden testsflutter test --tags golden --update-goldens # Update golden files