How to create a Modular Application with Flutter — Part 3
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!