Goal
I would like to handle the entire process of generating the HTML report with test coverage data through Bazel.
Components
In order to achieve my goal I understand that the following components are necessary:
- lcov .dat file: provides information about
what parts of a program are actually executed (i.e. "covered") while running a particular test case . I can generate the required lcov files for my project by running
./bazelw query "attr(name, '.*test_main', //...)" | xargs ./bazelw coverage --combined_report=lcov
(all my test targets are namedtest_main
, that's how I can execute thecoverage
command in all of them and combine the results with--combined_report=lcov
; - genhtml: an executable that can parse the lcov file and generate a HTML test report out of it (the final goal);
- coverage.blz: A custom bazel rule that takes the
.dat
file and thegenrule
binary as inputs and spits the final HTML and its deps (images and other HTMLs);
What I was able to do so far...
Create an executable script for genhtml
I'm not sure if this is the best approach, however, it seemed reasonable to me at this point:
#!/bin/zsh
TOOLS_ROOT="${HOME}/.devxp/tools"
LCOV_BIN_HOME="${TOOLS_ROOT}/lcov/bin"
LCOV_GIT_REPO="https://github.com/linux-test-project/lcov.git"
GENHTML="${LCOV_BIN_HOME}/genhtml"
function main () {
if [[ ! -f "${GENHTML}" ]]; then
_install &> /dev/null
fi
"${GENHTML}" "${@}"
}
function _install () {
mkdir -p "${LCOV_HOME}"
pushd "${TOOLS_ROOT}" || true
git clone "${LCOV_GIT_REPO}"
cd "${LCOV_HOME}" || true
make install
popd &> /dev/null || true
}
main "${@}"
Create a file group to access the .dat in the repository
Following the suggestions from - Using Bazel to generate coverage report;
filegroup(
name = "coverage_files",
srcs = glob(["bazel-out/**/coverage.dat"]),
visibility = [
"//visibility:public"
]
)
This lives in my repository's root BUILD
file
Start my custom rule
On file coverage_report.bzl
def _coverage_report_impl(ctx):
dat_lcov_file = ctx.attr.coverage_files
coverage_report = rule(
implementation = _coverage_report_impl,
attrs = {
"coverage_files": attr.label(),
},
)
In the context of the custom rule implementation, I have the following questions:
- QUESTION 1: I don't know if at this point the .dat file was already generated since it requires
bazel coverage
to have ran. Can I force bazel coverage from here? - QUESTION 2: I don't know how to get reference to my executable
genhtml
tool inside here. My plan was to do something likegenhtml *.dat -o output
; - QUESTION 3: I don't know how to specify the output files of the
genhtml
as the output for this rule (as you can see this is the first time I attempt to implement my own rule);
Any help is very much appreciated!
Reference Material