Flutter Widget test cannot emulate different screen size properly Flutter Widget test cannot emulate different screen size properly flutter flutter

Flutter Widget test cannot emulate different screen size properly


That is because of the font difference used by flutter test and flutter run.

Flutter's default font is Roboto for Android if you did not change it other font.

  1. Default Android: Roboto font and for iOS: San Francisco font
  2. Customize https://flutter.dev/docs/cookbook/design/fonts

Either 1) or 2) these fonts are not available to flutter test by default. Flutter test purposely uses a font called Ahem which is made out of square blocks that you see on your screenshot.

This is a preview:

enter image description here

Ahem font square are wayyy bigger than the normal that you are using. Therefore, it causes the RenderFlex overflow error

Solution

To achieve a near perfect emulation of your device in flutter test you have to download the font data then load the exact font that you are using.

To load a font in widget test, you should do inside the testWidgets function or setUp:

final flamante = rootBundle.load('assets/fonts/Flamante-Roma-Medium.ttf');      await FontLoader('FlamanteRoma')        ..addFont(flamante)        ..load();

Then add this font to the ThemeData before pumping the widget.

 theme: ThemeData(              fontFamily: 'FlamanteRoma', ),

The final test.dart code is:

import 'package:flutter/material.dart';import 'package:flutter/services.dart';import 'package:flutter_test/flutter_test.dart';import 'package:example/test/compare_test_size.dart';void main() {  testWidgets(    "Emulate real screen size",    (WidgetTester tester) async {      final flamante = rootBundle.load('assets/fonts/Flamante-Roma-Medium.ttf');      await FontLoader('FlamanteRoma')        ..addFont(flamante)        ..load();      // Adjust these to match your actual device screen specs      final width = 411.4;      final height = 797.7;      tester.binding.window.devicePixelRatioTestValue = (2.625);      tester.binding.window.textScaleFactorTestValue = (1.1);      final dpi = tester.binding.window.devicePixelRatio;      tester.binding.window.physicalSizeTestValue = Size(width * dpi, height * dpi);      await tester.pumpWidget(        MediaQuery(          data: MediaQueryData(),          child: MaterialApp(            home: TextScaleComparaison(),            theme: ThemeData(              fontFamily: 'FlamanteRoma',            ),          ),        ),      );      await expectLater(        find.byType(TextScaleComparaison),        matchesGoldenFile("text.png"),      );    },  );}

Now re generate the golden test and check the png. You will see real text, not boxes anymore:

test/test.png

enter image description here

And don't forget to add the same font in your main.dart

runApp(    MaterialApp(      home: TextScaleComparaison(),      theme: ThemeData(        fontFamily: 'FlamanteRoma',      ),    ),  );

And also don't forget to update pubspec.yaml and run flutter pub get

- family: FlamanteRoma  fonts:    - asset: assets/fonts/Flamante-Roma-Medium.ttf


As Curly already mentioned here, you can overwrite the tester.binding.window.textScaleFactorTestValue with a lower value. 0.8 was working well for my used fonts, but depending on your setup, you might use even a lower value. In this way, you don't need to await the loading of your fonts in each test case.