Flutter golden testing - generating tester views sized to your mobile devices
Creating tests for various size viewports can help us look for wrapping and sizing regressions. Our goal is to run the same test across several different-sized displays looking for regressions in the individual display sizes. We can do that by sizing the canvas just before loading the widget tree and running the golden test comparison.
We need either the viewport size for the device or the raw size of the device in pixels and its DPR. So currently this test code accepts the raw size and the DPR. The alternative is to just run the MediaQuery against the device and accept its width and height with a DPR of 1.0. The test code below supports both.
Test Code
There are two tests, one for the Pixel 3a and the other for the Pixel 4XL. Both tests pass in the raw pixel size and the Flutter DPR. The test
- Sizes the canvas to the device geometry.
- Brings up the demo app
- Creates/validates a golden image snapshot of the viewport
The test app is the MediaQuery code listed in a previous blog article https://joe.blog.freemansoft.com/2023/08/better-golden-testing-understanding.html
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_media_query/main.dart';
/// Converts the size to a DPR 1.0 size and get the correct relative sizing
/// The test canvas / web is a DPR=1.0 device
/// This only provides the expected results if we load our fonts because the
/// Ahem font is much wider than our standard font
///
/// This can be used in two ways
/// 1. accept the device physical dimensions and the DPR as calculated by the Google viewport
/// 1. Accept the logical viewport dimensions and a DPR of 1.0
Future<void> configureTesterForSize(
WidgetTester tester, Size canvasSize, double devicePixelRatio) async {
Size convertedSize = Size(canvasSize.width / devicePixelRatio,
canvasSize.height / devicePixelRatio);
await tester.binding.setSurfaceSize(convertedSize);
tester.view.physicalSize = convertedSize;
tester.view.devicePixelRatio = 1.0;
}
void main() {
/// Test the pixel 3a sized device
testWidgets('Golden Test Pixel 3a', (WidgetTester tester) async {
// Build our app and trigger a frame.
await configureTesterForSize(tester, const Size(1080, 2220), 2.75);
await tester.pumpWidget(const MyApp());
await expectLater(
find.byType(MyApp), matchesGoldenFile('main-pixel3a-actual.png'));
});
/// test the much larger 4XL sized device
testWidgets('Golden Test Pixel 4XL', (WidgetTester tester) async {
await configureTesterForSize(tester, const Size(1440, 3040), 2.75);
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
await expectLater(
find.byType(MyApp), matchesGoldenFile('main-pixel4XL-actual.png'));
});
}
Font loader Code so we don't use the Ahem font
Must be located and named: test/flutter_test_config.dart.
import 'dart:async';
import 'dart:io';
import 'package:golden_toolkit/golden_toolkit.dart';
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
return GoldenToolkit.runWithConfiguration(
() async {
await loadAppFonts();
await testMain();
},
config: GoldenToolkitConfiguration(
// Currently, goldens are not generated/validated in CI for this repo. We have settled on the goldens for this package
// being captured/validated by developers running on MacOSX. We may revisit this in the future if there is a reason to invest
// in more sophistication
skipGoldenAssertion: () => !Platform.isMacOS,
),
);
}
It assumes you have something like the following in your pubspec.yaml
flutter:
uses-material-design: true
fonts:
- family: Roboto
fonts:
- asset: assets/fonts/Roboto/Roboto-Regular.ttf
Related stuff by Joe
Resulting Pixel 3A golden image
This is the resulting golden image created and validated by the test after we loaded Roboto fonts into the test jig.
Note: The height is off compared to what is returned by MediaQuery on the device by about 25 pixels.
Resulting Pixel 4XL sized image
This is the resulting golden image created and validated by the test after we loaded Roboto fonts into the test jig.
Note: The height is off compared to what is returned by MediaQuery on the device by about 25pixels.
Comments
Post a Comment