Flutter: Easily add CI testing with GitHub Actions

One of the great things about Github Actions is how easily it lets you setup continuous integration testing for your flutter applications. In this post we’ll go through the basic implementation of a CI workflow in flutter.

Step 1: Create some tests

The first step in CI testing is obviously to write some tests! Writing the actual tests is highly domain specific and beyond the scope of this article, but you can check out the documentation to learn how it works. Or, if you’re interested in using the new integration_test library, you can see our post on that here.

For now lets assume you’re using the legacy widget tester (not integration_test). You should and have at least one file in the /test folder, suffixed with _test.dart that looks something like this:

void main() {
  testWidgets('MyApp smoke test', (WidgetTester tester) async {
    await tester.pumpWidget(const MyApp());
    // Add tests here!

With your tests prepared, you’re ready to set up your CI workflow.

Step 2: Create a .yaml file to configure a workflow

In your repo, create a file inside of .github/workflows named tests.yaml, with the following:

name: test-my-app
on: [push, workflow_dispatch]
    runs-on: ubuntu-latest
    - uses: actions/checkout@v1
    - uses: subosito/flutter-action@v1
    - run: flutter test

Some notes on the above script:

  • The push flag configures this workflow to run each time you push to your repo. workflow_dispatch shows a button on github.com that allows you to run it manually.
  • The runs-on: ubuntu-latest runs the tests on linux, which is the cheapest option (this only really matters if your repo is private).
  • The flutter test command runs all files named _test in the /test folder.

Once this file is added, it should begin working immediately. Check out the “Actions” tab in github.com to view the progress:

After a couple of minutes, your test should be complete!

Step 3: Surface the results with a badge

The last step is to clearly display whether your tests have passed or failed. One way to do this is to embed workflow badges at the top of your README.md file:

To add a badge, just add the following to the top of your readme file:

<a href="https://github.com/[USER_NAME]/[REPO_NAME]/actions"><img src="https://github.com/[USER_NAME]/[REPO_NAME]/workflows/test-my-app/badge.svg" alt="Build Status"></a>

Note that the test-my-app in the badge link, matches the name: test-my-app field in the workflow file itself which is how the badge knows which test it is tied to. The name of the .yaml file is not important.

With this you should have a working CI testing workflow. Congrats!

Using the integration_testing package

Using the new integration_test library is a little tricky, as it requires a target device, yet is not currently stable for linux or web targets.

Testing with android or ios requires simulators which is more work to configure and slow to execute. Windows and macOs are both viable options, but macOs build minutes are twice the cost as Windows. Based on all of that, we’ve found windows testing to be the best option for now.

To test with windows desktop, there are a few changes required to the workflow file:

  • modify your target build system to windows-latest
  • run the config --enable-windows-desktop command
  • add the -d windows flag
  • pass in the location of your test file
name: test
on: [push, workflow_dispatch]
    runs-on: windows-latest
    - uses: actions/checkout@v1
    - uses: subosito/flutter-action@v1
        channel: 'beta'
    - run: |
           flutter config --enable-windows-desktop
           flutter test -d windows integration_test/smoke_test.dart

That’s it, you’re done! Your tests will now run with every push. Happy coding!

Need help building something cool in Flutter? We’d love to chat.


Shawn has worked as programmer and product designer for over 20 years, shipping several games on Steam and Playstation and dozens of apps on mobile. He has extensive programming experience with Dart, C#, ActionScript, SQL, PHP and Javascript and a deep proficiency with motion graphics and UX design. Shawn is currently the Technical Director for gskinner.



  1. Thank you for the content you provided us. Thank you very much

  2. Very Helpful Tnx!

Leave a Reply

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