Testing in Flutter
It’s clear that Flutter is a way to create beautiful UI cross platform, and the developer experience is lauded my many (not just me). But what about the not so pretty things … TESTING!!
Some people love testing apps, I haven’t met any myself, but I hear some do. I personally don’t mind unit testing, especially in Android as Junit and Mockito are just easy to use. UI testings, urgh, espresso is painful, and most companies seem to want a cross platform solution like Appium. So lets take a look at unit testing, some widget testing, and finally UI testing on a Flutter project…
With unit testing, I found it very similar to Junit and Mockito. It uses the
flutter_test library, and the
A unit test file could look something like this:
- Each test class has to be named
your_class_name_test.dartthis will ensure that they are run when executing
setUpwill execute before each test inside the file
setUpAllwill execute once before all tests
tearDownwill execute after each test inside the file
tearDownAllwill execute once after all tests
testcan be synchronous or asynchronous depending on what is needed.
Mocking and Assertions
As Dart doesn’t have reflection (well Flutter Dart doesn’t), it’s not quite as easy as in Java / Kotlin world to make mocks. But thanks to the
mockito library and
build_runner it’s also not hard.
Simply just add an annotation for
@GenerateMocks and list the classes you want to mock. After you’ve added them run the following command
flutter pub run build_runner build
This will generate mock classes for you. So now
MockUser exist, and can be used inside tests.
So lets look at some simple mocking:
As you can see we pass our
MockFirebaseAuth into the
MyAuth constructor. Now we’re able to control what a function returns, verify that functions were called. We’re also able to use argument matchers and captures, full details can be found here https://pub.dev/packages/mockito
expect(actual, matcher) so in the example above we expect the user returned from
getCurrentUser to be equal to
mockUser as that is what we returned from
There are many matchers that can be used like:
hasLength— for checking a lists length for example
containsValue— for checking a map has a specific value
isNull— for checking a value is null
many many more can be found here https://api.flutter.dev/flutter/flutter_test/flutter_test-library.html
Integration Testing / Widget Testing
As everything in Flutter is a Widget, Widget testing means we can test UI logic without the need for a device / emulator. We can test an individual component, a page, or even the entire app (as that too is a widget).
The test file looks very similar, and can be inside the same file as general unit tests if you wanted:
Instead of using
test we use
testWidgets which provides a
WidgetTester. So lets create a simple page, and try and test a few things:
A simple page, with an
AppBar and an
ElevatedButton . When the button is pressed we set the
pageTitle triggering a rebuild and that String to be used in the
- The first test adds the
MainPageto an app, so it can be tested. Then searches for “Not set” and expects to find this once in the page
- The second test adds the
MainPagewidget again. This time taps the
ElevatedButton. Now it calls
tester.pump()to make sure that the state change takes effect, and then expects to find “Hello World” once in the page.
These are very simple tests, but you can test a lot with Widget Tests and gain a lot of test confidence in the app.
More information on widget testing can be found here https://docs.flutter.dev/cookbook/testing/widget/introduction.
Very simply, just do the same as the Widget Tests but create the files in the
integration_test folder. Instead of starting a widget, start the app itself…
In this test I’m testing one of my own Flutter apps. Clicking on “Host a session” should show a login bottom sheet…
- We start the app
pumpAndSettleto make sure that all animations have finished
- Tap on the “Host a session” button
- Expect a Widget with type
LoginBottomSheetContentto be visible
At the moment, Appium doesn’t support Flutter apps itself. However, there does seem to be support from the community. Browserstack have a page advising how to use this here https://www.browserstack.com/guide/test-flutter-apps-with-appium
As I’m not an Appium developer, I’m not going to attempt this.
Again, it appears that Flutter have developed with hindsight. Unit testing is well thought out, Widget testing is very powerful, and UI testing also just as good.