Test your Flutter widgets using golden files

Martin Kamleithner
The Startup
Published in
4 min readMar 1, 2020

Flutter has a powerful feature to test the look of your UI down to the pixel. Flutter can also render Widgets in tests, so we can leverage this to test how widgets get rendered with different screen sizes and get notified when the look of a widget changes. This feature is called “goldens”.

It’s pretty easy to use, but there are a few gotchas. Let’s look into it.

First, let’s create a simple widget that we will test later.

This Widget shows tiles in a grid. The wider the screen is, to more columns the grid will have.

Let’s write a golden file test for it:

We use the same theme as in the main app, the ensure a consistent look. We also wrap the widget in a Scaffold, the ensure the default text styles from the Theme are applied automatically.

We need to run

flutter test --update-goldens

the first time after editing golden tests, so all the initial golden images get regenerated.

A file called grid.png has been created in the goldens/ directory in the test directory. Let’s look at the image:

Hm. Golden files uses a resolution of 800x600 by default, which is not what we want for our Flutter app. Also, text rendering does not seem to work.

Loading custom fonts

appTheme uses custom fonts, which are not loaded in golden tests:

If we want to use custom fonts in golden tests, we need to load them first:

We can now call loadFonts() in setUpAll().

Let's try running flutter test again:

flutter test
00:03 +0: test the grid
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected: one widget whose rasterized image matches golden image "goldens/grid.png"
Actual: _WidgetTypeFinder:<exactly one widget with type "MyResponsiveGrid" (ignoring offstage
widgets): MyResponsiveGrid(dependencies: [MediaQuery])>
Which: Golden "goldens/grid.png": Pixel test failed, 1.85% diff detected.
Failure feedback can be found at /.../test/failures

Great! The widget now renders differently, so our golden tests fail. Flutter automatically generates a “failures” directury, that contains the expected image, the actual image and the difference between those two:

Actual image vs expected Image
Difference between the two images (isolated and masked)

The new images render the text correctly because now we load the fonts. We first generated the golden files without loaded fonts, so we have to update the golden files again using

flutter test --update-goldens

Testing different screen sizes

If we don’t like the default resolution of 800x600, we need to tell the framework our desired screen size.

Unfortunately, this is a bit involved, but we can abstract the details away nicely (Thanks to aanelson for this snippet):

setting the screen size for widgets tests

We can now test our widget with different screen sizes:

Don’t forget to set a default screen size in tearDown() to ensure the tests stay order-independent.

Let’s look at the results:

generated golden images with custom screen size

Great! The image with a resolution of 960x540 logical pixels has 3 columns, while the image with a resolution of 540x960 has 2 columns.

Conclusion

Golden Tests are a very powerful feature to protect against accidental changes of your UI and to test different screen sizes. Regenerating the golden images after purposeful changes to the UI is a breeze and only one

flutter test --update-goldens

away.

Correctly setting loading the fonts and setting different screen sizes requires some effort and could be improved in the future, but it only needs to be set up once and can be reused for all subsequent tests.

This article focused mainly on the basics of golden tests. If you want to take it to the next level, I recommend this excellent article from the guys at eBay.

--

--