How to create a Modular Application with Flutter — Part 3

Alvaro Armijos
3 min readApr 21, 2024

--

In this final article, we will explore how to test each module and obtain a consolidated code coverage report for the whole project.

With the help of Melos, we will create a script to run all Flutter tests in this project.

# The name of the project (required) is used for displaying purposes within IO environments and IDEs.
name: star_wars

# A list of paths to local packages that are included in the Melos workspace. Each entry can be a specific path or a glob pattern.
packages:
- packages/**
- .

command:
bootstrap:
usePubspecOverrides: true

scripts:
unit_test:
run: melos exec --dir-exists="test" --fail-fast -- flutter test --no-pub --coverage
description: Run all Flutter tests in this project.

When we run the melos unit_test command, it runs all the Flutter tests in the modules that have a test folder, and also generates code coverage for each module. Our task is to find a way to aggregate all of the code coverage reports from each module into a single report, and thereby obtain the code coverage for the entire project.

We will use LCOV, a graphical tool for coverage testing. LCOV generates HTML pages containing coverage information.

Installing LCOV

Mac

brew install lcov

Linux

Installation on Ubuntu/Debian:

sudo apt-get update
sudo apt-get install lcov

Installation on other Linux distributions:

sudo dnf install lcov

Windows

Using Chocolatey (Windows package manager). Open a terminal or PowerShell with administrator privileges and run:

choco install lcov

Compiling from source:

If you prefer to compile from source, you can clone the LCOV repository and build it following the instructions on its official GitHub page: LCOV on GitHub

Now we will use a script combine_coverage.sh to combine all the coverage reports from each module into a single file. This script needs to have execution permissions, which can be granted using the following command: chmod 777 scripts/combine_coverage.sh

#!/usr/bin/env bash

escapedPath="$(echo `pwd` | sed 's/\//\\\//g')"

if grep flutter pubspec.yaml > /dev/null; then
if [ -d "coverage" ]; then
# combine coverage from package tests to a common file
if [ ! -d "$MELOS_ROOT_PATH/coverage_report" ]; then
mkdir "$MELOS_ROOT_PATH/coverage_report"
fi
sed "s/^SF:lib/SF:$escapedPath\/lib/g" coverage/lcov.info >> "$MELOS_ROOT_PATH/coverage_report/lcov.info" --filters \.g\.dart
rm -rf "coverage"
fi
fi

Now with Melos, we will create a script to run all Flutter tests using the unit_test command, then we will execute the combine_coverage.sh script to combine all coverage reports, and finally, we will use LCOV to generate the HTML coverage report.

# The name of the project (required) is used for displaying purposes within IO environments and IDEs.
name: star_wars

# A list of paths to local packages that are included in the Melos workspace. Each entry can be a specific path or a glob pattern.
packages:
- packages/**
- .

command:
bootstrap:
usePubspecOverrides: true

scripts:
unit_test:
run: melos exec --dir-exists="test" --fail-fast -- flutter test --no-pub --coverage
description: Run all Flutter tests in this project.
gen_coverage:
run: |
melos run unit_test
melos exec -c 1 -- "\$MELOS_ROOT_PATH/scripts/combine_coverage.sh"
lcov --remove MELOS_ROOT_PATH/coverage_report/lcov.info "**/di/" -o MELOS_ROOT_PATH/coverage_report/lcov.info
coverde value -i MELOS_ROOT_PATH/coverage_report/lcov.info > MELOS_ROOT_PATH/coverage_report/result.txt
melos exec -c 1 -- genhtml \$MELOS_ROOT_PATH/coverage_report/lcov.info -o \$MELOS_ROOT_PATH/coverage_report/html

Finally, if we run melos gen_coverage followed by open coverage_report/html/index.html, we will obtain a coverage report in this format:

The test coverage of this project is 76,9%.

This concludes the final article in this series. Below, you can find the complete code:

If you like it, you can Buy Me A Coffee!

--

--

Alvaro Armijos

Electronic and Telecommunications Engineer | #Flutter Developer 💙 | Always eager to learn | https://www.linkedin.com/in/alvaro-armijos-sarango/