Unit Tests and Coverage Reports in Multi-package Flutter Project
When developing a side project, or relatively small project, it is common to use a single flutter package where all the code resides. To improve it further, the code can be separated into multiple folders such as data, domain, presentation layers, and even feature folders.
However, for more complex projects, this monolith architecture may not be scalable. The developer team might grow and, in the end, different teams own specific part of the applications, like “core package”, “design package” and etc. Even further, some packages might be moved to another repository.
In this article, I will not discuss the pros and cons of both approaches, instead, I will mainly focus on the unit tests and code coverage part for the multi-package projects. To handle multi-package architecture, and to execute the flutter commands like
flutter analyze in every package, we are using a third party library, Melos. You can ask yourself, do we really need another library to manage multiple packages? The answer would be: No, you can create and maintain your own scripts and run them for every packages or for specific packages. However, Melos will make your life easier with its powerful functionality. You can check what you can do with Melos here.
How to use Melos?
Melos can be installed as a global package via pub.dev. Copy the following command to your terminal to install Melos.
dart pub global activate melos
Melos requires a few one-off steps to be completed before it can be used. To set up the project to use Melos, create a
melos.yaml file in the root of the project.
melos.yaml file, add
Once installed & setup, Melos needs to be bootstrapped. Bootstrapping has 2 primary roles:
- Installing all package dependencies (internally using
- Locally linking any packages together.
Unit tests scripts, coverage scripts and more…
At this point, we have already installed and setup the melos. So we can dive into the script part. We can use existing command like
flutter analyze or create our own scripts and run these scripts in every package with the help of
melos exec command. Here is a few example of scripts that we use in our project:
analyze script run
flutter analyze in every package with the help of
unit-test script runs the
flutter test --no-pub --coverage in every package that contains “test” folder with the help of
melos exec. Since we add
--fail-fast argument to the
melos exec command, the script will complete if any of the tests cases fail.
unit_test_and_coverage script removes the generated coverage folder first, then run the
unit-test script. After this step, a coverage folder will be generated for every package that has test folder in it. Then melos will execute
coverage filter --input ./coverage/lcov.info --output MELOS_ROOT_PATH/coverage/filtered.lcov.info --filters \.g\.dart command for every package that has
coverage/lcov.info file. At the end, all the coverage reports excluding the filtered files
\.g\.dart will be merged under the
<project_root>/coverage/filtered.lcov.info file. As the next step
coverde toolv will check the coverage file and write the result to
This file shows the individual code coverage percentage for every file, and also at the end, it shows the overall code coverage of the project. The output of the command is written to this file because, later, we can parse this file in CI/CD platforms, and have a code coverage check in Pull Requests 😉. If you don’t want to do this, you can also ignore
> MELOS_ROOT_PATH/coverage/result.txt part.
To run the
unit_test_and_coverage script, coverde cli tool needs to be installed:
dart pub global activate coverde
How to visualise the generated coverage report?
When we run
unit_test_and_coverage with melos, a filtered and merged coverage report file is generated, but, this file format is not user friendly. When we open the file we see something like this:
To generate an html report out of that, we have to do the following:
# install the lcov tool to convert the lcov.info file to html files.brew install lcov# generate html file by giving the input and output pathsgenhtml coverage/filtered.lcov.info -o coverage/html
After running the above commands, when we open the main index file, we can see an informative, nicely formatted html reports. From there, we can navigate through files and see the coverages line by line.
What is next?
I hope you find the article informative and enjoy while reading ☺️. As the next step, I will explain how we can use CI/CD platforms to generate this code coverage report and use it in the PR checks. I will also explain how to generate a fancy coverage badge and display it in our repository.
Feel free to comment, and ask for more information if needed. You can also connect with me on LinkedIn ☺️.