Weighted Code Coverage is a tool that implements some metrics aiming to merge information regarding coverage and complexity into a single value.
This repository uses rust code analysis
to analyze the project folder and grcov
to produce the coverage data used as weighted-code-coverage
input.
The implemented algorithms are:
- Weighted code coverage by Luca Ardito and others.
- CRAP by Alberto Savoia and Bob Evans.
- Skunk by Ernesto Tagwerker.
First of all, we need to introduce the concept of code space, which refers to any structure that incorporates a function, such as another function, a class, a struct, a namespace, or more generally, the unit scope. Therefore, the analyzed source code must be divided into code spaces.
Let c be a code space, if its complexity is greater than 15, its weight is equal to the total number of covered lines, otherwise is 0. To compute the Wcc of a file, one must take all the weights of the code spaces that compose it, sum them up, and then divide the result by the sum of Physical Lines of Code (PLOC) of all the considered code spaces. Wcc is a metric expressed as a percentage and, like coverage, it should be maximized.
Let c be a code space with coverage equal to
The CRAP of a file is computed with the same formula, using the average code spaces complexity as
Let c be a code space with coverage equal to
where
The Skunk of a file is computed with the same formula, using the average code spaces complexity as
To obtain the previous formula, we started from the introduction to the metric, whitin which the presented algorithm can be summarized by the following formula:
where
Analyzing it, we noticed that it presents some issues. First of all, the fact that if we consider a code space with complexity equal to 50 and maximum coverage of 100%, we get a Skunk equal to 2:
This value is anomalous, as despite the coverage being maximum, it is not reasonable for such a complex function to have such a low Skunk score.
To mitigate this issue, we have modified the formula as follows:
Another problem with this metric is that when we try to compute the threshold value, assuming coverage equal to 60% and complexity equal to 10, we notice that using a
which causes even code spaces with complexities up to 26 to be accepted by the metric, in fact a code space with maximum coverage of 100% and complexity equal to 26 would have a Skunk equal to 26:
Instead, defining a
Therefore, based on these considerations, we have decided to adopt the initially presented formula with a
Run weighted-code-coverage
on a project with the following command:
weighted-code-coverage [OPTIONS] --project-path <PROJECT_PATH> --grcov-format <GRCOV_FORMAT> --grcov-path <GRCOV_PATH>
Example with some options:
weighted-code-coverage --project-path /path/to/project --grcov-format coveralls --grcov-path /path/to/coveralls.json --thresholds 60.0,16.0,16.0 -t 8 -m files -s wcc --json /path/to/output.json --html /path/to/output/html/ -v
To specify the input grcov json file you must first select the format using --grcov-format
option followed by coveralls or covdir, and then specify the file path using --grcov-path
option.
coveralls example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format coveralls --grcov-path ./coveralls.json
covdir example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format covdir --grcov-path ./covdir.json
To choose the thresholds use --thresholds
option.
Example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format <GRCOV_FORMAT> --grcov-path <GRCOV_PATH> --thresholds 60.0,10.0,10.0
The default values are 60.0,10.0,10.0, and the values refer to: Wcc, cyclomatic complexity, and cognitive complexity.
The Wcc is a percentage value and an actual threshold, so following the convention commonly used also for coverage, we have assumed a default value of 60%.
The other two are complexity values, the first one refers to cyclomatic complexity, while the second one refers to cognitive complexity. The tool computes two variants for metric values: one considering cyclomatic complexity and the other considering cognitive complexity. The maximum value of a code space complexity should normally fall within the range [10, 15], although it is generally recommended to keep it below 10. A complexity exceeding 15 indicates a complex function which may require refactoring.
These two complexity values are used to calculate the threshold for CRAP and Skunk. Assuming a coverage value of 60% we obtain a CRAP threshold equal to:
and a Skunk threshold equal to:
A user can choose which complexity values will be used to compute Crap and Skunk thresholds, while the coverage value is fixed at 60%.
To choose the number of threads that will be used for the computation use --threads
or -t
option.
If not specified, the default value is:
Example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format <GRCOV_FORMAT> --grcov-path <GRCOV_PATH> -t 7
To choose the mode to use for analysis.
use --mode
or -m
option.
The supported values are files and functions. If not specified the default value is files.
Example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format <GRCOV_FORMAT> --grcov-path <GRCOV_PATH> -m functions
The files mode will return only the metric values of the files, while the functions mode will also show the metric values of the functions.
To choose which metric to use for the sorting of the output use --sort
or -s
option.
The supported values are: wcc, crap, and skunk. If not specified, the default value is wcc.
Example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format <GRCOV_FORMAT> --grcov-path <GRCOV_PATH> -s crap
The tool will produce by default a json output named wcc.json in the current directory. The user can change the path using --json
option.
Example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format <GRCOV_FORMAT> --grcov-path <GRCOV_PATH> --json ./wcc_output.json
In addition, it is also possible to obtain an html output, using the --html
option and specifying the path of the destination directory.
Example:
weighted-code-coverage --project-path <PROJECT_PATH> --grcov-format <GRCOV_FORMAT> --grcov-path <GRCOV_PATH> --html ./output/html/
- Install grcov latest version using cargo
cargo install grcov
- After grcov has been installed, install
llvm-tools component
:
rustup component add llvm-tools-preview
RUSTFLAGS
andLLVM_PROFILE_FILE
environment variables need to be set in this way
export RUSTFLAGS="-Cinstrument-coverage"
export LLVM_PROFILE_FILE="your_name-%p-%m.profraw"
- Then go to the folder of the repository you need to analyze and run all tests with
cargo test
- After each test has been passed, some
.profraw
files are generated. To print out the json file with all the coverage information inside, run the following command:
grcov . --binary-path ./target/debug/ -t coveralls -s . --token YOUR_COVERALLS_TOKEN > coveralls.json
- At the end, launch
weighted-code-coverage
with the desired options.
Released under the MIT License.