BradCypert.com
How to upload coverage to CodeCov for Dart and Flutter
May 19, 2022

How to upload coverage to CodeCov for Dart and Flutter

Posted on May 19, 2022  (Last modified on December 27, 2022 )
4 minutes  • 672 words
This project uses these versions of languages, frameworks, and libraries.
  • dart dart : 2.16.2
This tutorial may work with newer versions and possibly older versions, but has only been tested on the versions mentioned above.

Code Coverage helps you identify how much of your code is covered via test cases. Coverage itself is an interesting idea. People are largely divided on it but coverage can be a useful metric if used for objective information and not used to measure success. In this post, we'll cover generating coverage for flutter and dart (each individually), formatting that coverage if needed, and then uploading it to CodeCov via Github actions.

Dart and Flutter both ship with testing tools that are capable of producing coverage reports. Flutter generates a nice .lcov file for you and Dart... does not ☹️. If you're unaware, LCOV is the graphical frontend to GCOV, which is GCC's coverage testing tool. A lot of work has gone into LCOV so being able to leverage that file spec can be really beneficial. In Flutter, to get an lcov report, all we have to do is run flutter test --coverage and that will generate a file at ./coverage/lcov.info. If you'd like to display that in the browser, you can use the genhtml command from lcov. Try genhtml coverage/lcov.info -o coverage/html.

The `genhtml` command comes from LCOV, so to use `genhtml`, you'll need to install `lcov`. You can find the install instructions for LCOV here, but if you're able to use homebrew, `brew install lcov` should get you what you need, too!

Dart, however, does not give us a nice lcov coverage file. To generate our coverage files, we can run dart run test --coverage="coverage". This will generate a coverage folder with .json files for our coverage report. These, unfortunately, aren't lcov files (which CodeCov wants), but thankfully there's a tool we can use to format our coverage as an lcov file. You can run dart pub global activate coverage to add the coverage binaries to your pub_cache path. Running $HOME/.pub-cache/bin/format_coverage --lcov --in=coverage --out=coverage.lcov --packages=.packages --report-on=lib will convert your Dart coverage files to a single lcov file.

When you install coverage, you may see something like:
Warning: Pub installs executables into $HOME/.pub-cache/bin, which is not on your path.
You can fix that by adding this to your shell's config file (.bashrc, .bash_profile, etc.):
export PATH="$PATH":"$HOME/.pub-cache/bin"

Following the above instructions can help you turn $HOME/.pub-cache/bin/format_coverage into format_coverage, which is nice but our github actions container has a small issue with the pub cache not being on the path, so we'll reference it directly through the rest of this post.

Now that we have a path to standardize our Dart and Flutter coverage reports around lcov, we can shove all of this into a github actions workflow and get things uploading. To do this, we'll use the CodeCov action (codecov/codecov-action@v2 ). Creating our Github workflow should be relatively easy now that we've gone through the steps up to this point. You can define whatever name and on hooks that suit your needs, but the important part for now is the jobs section.

name: Dart CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:

    runs-on: ubuntu-latest

    container:
      image:  dart:latest

    steps:
    - uses: actions/checkout@v2
    - name: Install dependencies
      run: dart pub get
    - name: Run tests
      run: dart pub run test --coverage="coverage"
    - name: Install coverage tools
      run: dart pub global activate coverage
    - name: format coverage
      run: $HOME/.pub-cache/bin/format_coverage --lcov --in=coverage --out=coverage.lcov --packages=.packages --report-on=lib
    - uses: codecov/codecov-action@v2
      with:
        files: coverage.lcov
        verbose: true # optional (default = false)

This action will run your tests and generate a coverage report, then upload that to CodeCov. If you're using Flutter, you can swap out the Run tests step and remove the Install coverage tools and format coverage steps -- It's a lot simpler with just Flutter!

Just a heads up, Codecov works really easily with public repos, but there are a few more steps required to set up a private repo. The steps required (its mostly just generating and setting a token) can be found here: https://github.com/codecov/codecov-action#usage .

Cartoon headshot of Brad Cypert
Follow me

Connect with me to follow along on my journey in my career, open source, and mentorship. Occasionally, I'll share good advice and content (quality not guaranteed).