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 
  1. Sizes the canvas to the device geometry.
  2. Brings up the demo app
  3. 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

BlogBetter Flutter golden testing - how mobile logical sizing is different than the default golden size
BlogFlutter golden testing - generating tester views sized to your mobile devices
VideoFlutter Golden testing with views sized to your mobile devices
VideoFlutter golden testing - taking into account the Flutter logical resolution on mobile devices
Demonstration CodeFlutter media query example with tests

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

Popular posts from this blog

Understanding your WSL2 RAM and swap - Changing the default 50%-25%

Installing the RNDIS driver on Windows 11 to use USB Raspberry Pi as network attached

DNS for Azure Point to Site (P2S) VPN - getting the internal IPs