Automated Testing

If you’re serious about building robust, production-ready apps, how can you verify that your code is bug-free and behaves as expected?

Testing is the answer, and you have two options:

  • Manual Tests, which be carried out by testing all of your application’s features by hand. They are very error-prone and time-consuming and simply don’t work at scale.
  • Automated tests, which need to be written and maintained, but they run fast and often. They are also a good safety net that can help you find out if something breaks when you refactor your code.

Unit Tests, Widget Tests, Integration Tests

In Flutter, there are three types of tests: unit testswidget tests and integration tests. This page on the official documentation offers a quick overview:

For a quick tutorial about writing tests with some examples, I recommend this video:

This covers unit, widget, and integration tests and also explains how to use the mockito package. This is useful when testing individual parts of your application in isolation from the rest of the code (e.g. networking).

Note that with the introduction of Null Safety, mockito now relies on code generation and is a lot harder to use. So I recommend using mocktail instead, which offers the same API, but doesn’t require codegen.

For a more in-depth course, you can check out this entire playlist by Very Good Ventures:

Golden Image Tests

Alongside unit, widget and integration tests, a technique known as golden tests is sometimes used.

Golden tests allow you to compare a screen of your app with some reference image file, to ensure that each pixel in the UI matches exactly with the golden version.

This technique is quite useful if you want to verify that you don’t get UI regressions as you make changes. It is explained well in this article:

To make your life easier with golden tests, check the golden_toolkit package by eBay.

Integration Tests with Patrol

Patrol is a new testing framework for Flutter.

It builds on top of Flutter’s existing test tooling, allowing you to access native platform features (including permission dialogs, notifications, etc.) while extending the existing finder APIs, making them shorter and easier to understand.

It also works as a production-quality of Flutter’s built-in integration_test plugin by fixing some of its shortcomings and enabling features such as full isolation between tests and sharding.

For more info, read the docs:

This video from FlutterCon 2023 is also available:

Daily Challenge - Add some widget tests

In lesson 9, I challenged you to build a BMI calculator app:

Daily challenge: build a simple BMI calculator app

And today’s challenge is to add some widget tests to the same app that check the following:

  • First test: when the input weight field is empty, the output BMI text field should be empty.
  • Second test: when the input height field is empty, the output BMI text field should be empty.
  • Third test: when both the weight and height fields are not empty, the BMI text field shows the correct value.

If you need a little help, here is how you can find a widget by key and check that it exists:

final weightField = find.byKey(const Key('weight'));
expect(weightField, findsOneWidget);

And here is how you can enter some text into a TextField:

await tester.enterText(weightField, '70');

Happy coding!

Questions? Let's chat