Painless Testing of Flutter Apps with Nevercode

Testing your Flutter project is the cornerstone of a healthy app. When developing apps, it’s essential to verify that changes in the code don’t affect other parts of the app. It’s also important to make sure that the application’s functionality doesn’t break with the latest changes in the code. This can be achieved by writing a comprehensive suite of automated tests around each feature of the application. Flutter provides a solid testing framework which allows developers to write tests at unit, functional and UI level. Widget testing is one cool feature that Flutter provides to run UI tests as fast as unit tests.

In this post, we will cover how to test Flutter apps and how to apply continuous integration with Nevercode without any configuration using the Flutter-Demo app.

Testing Flutter Apps

Flutter has cool documentation on how to test Flutter apps at different levels with example code. In summary, Flutter allows developers to write tests at unit, widget and integration level.

Flutter Unit Testing

The purpose of unit tests is to verify that a single unit or method works well with different conditions or parameters. Flutter unit tests can be added with the package package:test and by adding the tests into the test directory at the root of the project. We can add a simple unit test by creating a file test/unit_test.dart with the following code:

import 'package:test/test.dart';

void main() {
  test('Test Addition', () {
    var answer = 42;
    expect(answer, 40+2);
  });
}

This test will verify if the addition works with different inputs and we can expect correct values. This is a very basic unit test, but in reality, we can add unit tests for the modules we write in apps. We can run the unit tests locally using the flutter doctor command. This command will run all the tests inside the test directory. If you want to run an individual unit test, we can run it by passing the relative path, like this:

flutter test test/unit_test.dart

Flutter Widget Testing

The widget testing feature of Flutter allows developers to verify the functionality of the widgets used in the app. We can launch a widget as part of the test and perform actions as real users do on the widget. An amazing thing about widget testing is that widget tests run as fast as unit tests whilst going through the UI. There are barely any other test frameworks which have this kind of feature. The widget tests for Flutter come up in the package:flutter_test package and have fluent API documentation available here.

We can add a widget test for our Flutter-Demo app by creating test/smoke_test.dart with the following content:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:flutter_demo/main.dart';

void main() {
  testWidgets('smoke test', (WidgetTester tester) async {
  final app = MyApp();
  await tester.pumpWidget(app);
  expect(find.text("0"), findsOneWidget);
  await tester.tap(find.byIcon(Icons.add));
  await tester.pump();
  expect(find.text("1"), findsOneWidget);
  });
}

This test launches the Flutter demo app, pumps the widgets, asserts that the count is initially 0 and then taps on the add icon to assert that the count has been incremented to 1. You can see that this test covers a lot of user actions but with incredibly fast speed. We can run this test similarly to unit tests with the flutter doctor command. The widget testing feature is truly amazing.

Flutter Integration Testing

Flutter integration tests are similar to Xcode UI tests or Android Espresso tests which go through the UI to perform specific operations. The Flutter integration tests run in a separate process and can be run on real devices or on simulators or emulators. Flutter provides a separate package, Flutter Driver, to drive these tests. In order to enable those tests in our app, we have to add the flutter_driver package to pubspec.yaml and write integration tests in the test_driver directory at the root of the project.

We also need to create an instrumented app and enable the Flutter driver extension using the enableFlutterDriverExtension() method. You can find the details of the setup on Flutter documentation, or read an excellent post on how to set up integration testing for a Flutter app here.

We have written an integration test to test the message on the screen here, we can run this test locally using the flutter drive command line tools as follows:

flutter drive --target=test_driver/main.dart

This test will launch the app on the simulator or the emulator and will then assert that the message appears on the screen.

Testing Flutter

We can set up the integration tests on real devices and watch them run to gain confidence in the app.

Testing Flutter on Nevercode

Now we have seen how to run Flutter tests locally, but in order to run them on a continuous basis on every code change, we need a continuous integration server. The process of setting up the tests on a CI server usually requires some setup and configuration, but with Nevercode it is entirely painless as:

  • Nevercode analyzes the Flutter project and provides an option to enable the Flutter tests;
  • Nevercode also scans the code for integration tests and provides an option to enable the Flutter driver tests.

Flutter Testing

We just need to enable the unit, widget and integration tests in the UI to allow them to be run on Nevercode.

In our previous blog post, we set up a Flutter-Demo project on Nevercode. We can now just add the testing option and run the build on Nevercode to get instant feedback on our tests. Once we have enabled the tests on Nevercode, we can see in the build logs that all the tests were run during the build and that testing took just a couple of minutes.

Flutter Testing

Now that we have set up our Flutter unit, widget and integration tests on Nevercode in a few button clicks, we can run them on any branch or after every commit to the main branch to get early feedback during app development.

Source Code

You can find the source code of all the Flutter tests described here on the Flutter Demo app on Github. You can clone the project and run widget and integration tests as follows:

$ git clone https://github.com/Shashikant86/Flutter-Demo

$ cd Flutter-Demo

$ flutter tests

$ flutter drive --target=test_driver/main.dart

Conclusion

Getting regular feedback on your automated tests is critical in mobile app development. Flutter provides a great automated testing framework to test the app at unit, widget and integration level, and with Nevercode we can automate running the automated tests as part of Continuous Integration without any setup or configuration.

 


This article is written by Shashikant Jagtap.

Shashikant is DevOps practitioner for mobile apps and Director at XCTEQ Limited. He has automated release pipelines, implemented CI/CD and enabled DevOps cum Test Automation practices for many apps.

He blogs about mobile DevOps and CI/CD. Check-out XCTEQ for more: https://www.xcteq.co.uk/

 

Leave a Reply

Your email address will not be published. Required fields are marked *