This is a follow up to my previous post on getting started with Flutter and GitHub Actions, if you haven't worked with Actions before you might want to start there.

In the previous post we set up a simple CI pipeline to build my Fructika app with three steps (build, analyze and test) running on an Ubuntu Linux VM , the YAML for which looks like this.

on: push
jobs: 
  build-and-test: 
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1 
    - uses: actions/setup-java@v1
      with:
        java-version: '12.x'
    - uses: subosito/flutter-action@v1
      with:
        channel: 'stable' 
    - run: flutter pub get
    - run: flutter build aot
    - run: flutter analyze
    - run: flutter test

That's a great start and now I'd like to upgrade my CI to monitor the level of code coverage that I am achieving with my tests.

Code Coverage with Codecov

It can be a challenge to ensure code has good test coverage, for me one way to help keep up the motivation to achieve that is having clearly visible metrics. There are a couple of great hosted and self-hosted services available that will collect and share metrics for you. For this project I chose Codecov because it supports Dart, provides a free plan for open source projects, and has a verified Action available in the GitHub Marketplace.

Codecov - GitHub Marketplace
Group, merge, archive and compare coverage reports

Flutter, handily, has built in support for outputting test coverage. If I append the --coverage argument when running tests from the command line, then test coverage will by default be written to coverage/lcov.info. So, all I need do to gather test coverage data is modify my test step.

# Run tests and write code coverage results
- run: flutter test --coverage

To push the results to Codecov I had to sign up for an account, add the Fructika repository to my account and grab the Repository Upload Token.

Codecov Repository Upload Token

Next, I inject this token into my workflow as a secret by navigating to the Settings tab of my repository and choosing Secrets from the left-hand menu.

GitHub Secrets

I then click Add a new secret give the secret a name, paste in my token and click Add secret.

Add a new secret

I can reference that secret anywhere in this repo's actions via this syntax ${{secrets.CODECOV_TOKEN}} and now publishing my code coverage results is as easy as using the Codecov step, passing it my token and the path to my coverage file.

- uses: codecov/[email protected]
  with:
    token: ${{secrets.CODECOV_TOKEN}}
    file: ./coverage/lcov.info

A very brief aside on Secrets

If at this point you're thinking: "Secrets seem to provide a great way to securely store all the config/token/keys I don't want visible in my repository but I do want to use during my build or inject into my application?". Well then, you'd be right, and I'd encourage you to go look into the docs about them to find out more.

But back to code coverage, now on every successful build I have a step that will publish my code coverage results to Codecov which will collect them and allow me to view the current state of code coverage in my repo and track that over time in nice looking charts that I can drill into like this:

Codecov also provide a badge showing your coverage that you can link to the code coverage report. You can embed the badge in your readme or any other markdown using the following syntax:

[![codecov](https://codecov.io/gh/{GITHUB_USER}/{GITHUB_REPO}/branch/master/graph/badge.svg)](https://codecov.io/gh/{GITHUB_USER}/{GITHUB_REPO})

So, for the Fructika repo that mark down looks like this:

[![codecov](https://codecov.io/gh/adam7/fructikav2/branch/master/graph/badge.svg)](https://codecov.io/gh/adam7/fructikav2)

And renders as this clickable badge codecov

Thanks for reading I hope you found this helpful, if you have any questions or suggestions feel free to ping me on twitter. In the next post I'll be talking about Matrix testing ...

Photo Credit Kate Stone Matheson