This article will talk about the following items in sequence
Before talking about why code coverage is important I want to list down some important principles for code coverage from my experience
Apparentlly, code coverage is not a silver bullet to improve code quality, why do we bother to do it? Here are the reasons
We will know things we don’t know
It is pretty hard to figure out how many logic branches in our codebase for a human brain. But even an intel Celeron PC can point out the missing branches and statement in just a second
This will help engineers to rethink carefully about logic branches. Sometimes the logic can just be much simplier to achieve the same goal
I am having the opinion that unit tests automatically help you write better code
If you write a giant method that is packed with tons of conditions. In the same time, it also depended on complex inputs
I will assure you would suffer when it comes to write tests with a reasonable coverage
Lowly coupled, highly cohesive code will be a natural result with good unit test and coverage
The changing in codebase is inevitable. Especially in the mordern software engineering world, we reply on a lot of dependencies
Things can be tricky when changing them.
A good code coverage will at least help you to ensure the bottom line of quality
Good articles to share
What is the defination of code Coverage
Google Code Coverage Best Practices
The importance of Code coverage
Flutter provides an efficient and out-of-box testkit. People don’t need to fight for their favourite framework like the javascript world(Jest vs Jasmine)
By running the following command in a flutter project, it will generate a coverage folder which contains an lcov.info
flutter test --coverage
In order to see the coverage in VS code nicely, I would recommend 2 extensions
But if the coverage folder is not on the root directory of project, you might need to configure it something as below
"flutter-coverage.coverageFilePaths": [
"client/user/coverage"
]
With these 2 plugins you will get something like this:
Another way of viewing it is to convert the lcov.info into a html report.
By running the following command, a html report will be generated. install lcov is a prerequisite
genhtml coverage/lcov.info -o ./coverage/html
The Functions and Branches test coverage will have no data from the out-of-box flutter test.
But there is a dart library from Dart team called package:coverage which supports it. But making them to work together is another long topic
Related discsussion
https://github.com/flutter/flutter/issues/108313
https://github.com/dart-lang/coverage/issues/141
Platform | Sonarqube (Self-hosted) | CodeCov | Github Actions |
---|---|---|---|
Description | Opensourced Platform for continuous inspection of code quality to perform automatic reviews | Platform dedicated for code coverage | Toolkit to automate your build, test, and deployment pipeline. |
Hard to customize | Low | High | Low |
Complexity | High | Low | Low |
Security concerns | High | High | Low |
Cost | High | Medium | Low |
Maintainance | High | Low | Medium |
From the above analysis, I decided to go for Github acions mainly for
– Security
I don’t really like the idea to send source code out to a 3rd party platform.
Especially there are some security breaches happened for both Sonaqube and CodeCov recently.
– Simplicity
I just want something simple to create good enough code coverage info during the pull request process
A self-hosted code quality platform like Sonarcube is an overkill for me
Also I don’t want to introduce another platform in our process just for this, that’s why I passed codecov on this too
– Synthesis
Due to all CI/CD workflows are running in Github, a github action can easily access all resources and reuse the logic from others.
As my personal preference I choosed Typescript action as base.
But there is a special thing for typescript action, it will take two steps to be compiled to the final deliverables.
typescript --> javascript --> bundled javascript
(tsc) (ncc)
The actual implementation is straightforward. It is mostly based on the native github libraries.
The shown implementation will be only working for Debian GNU/Linux due to the usage of apt-get.