Coverage support
Running tests with coverage
rules_scala supports coverage:
bazel coverage //...
It will produce several .dat files with results for your targets.
You can also add more options to receive a combined coverage report:
bazel coverage \
--combined_report=lcov \
--coverage_report_generator="@bazel_tools//tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator:Main" \
//...
This should produce a single bazel-out/_coverage/_coverage_report.dat
from all coverage files that are generated.
Processing coverage reports
You can install lcov
package (that supports the format Bazel uses for coverage reports) to have access to additional tools:
# Use your system package manager. E.g. on Ubuntu:
sudo apt install lcov
Having lcov
package installed you can extract information from your coverage reports:
# For a summary:
lcov --summary your-coverage-report.dat
# For details:
lcov --list your-coverage-report.dat
If you prefer an HTML report, then you can use genhtml
provided also by the lcov
package.
An example with a bit of ceremony:
# Output html reports to a new directory.
destdir="my-coverage-reports"
mkdir -p ${destdir}
# Generate HTML report from the results.
genhtml -o ${destdir} --ignore-errors source bazel-out/_coverage/_coverage_report.dat
echo "coverage report at file://${destdir}/index.html"
Support for testing frameworks
Coverage support has been only tested with ScalaTest.
Working around missing lambda coverage with Scala 2.12+
The current Jacoco version in Bazel (0.8.3) has missing coverage for lambdas
(including for comprehensions; see issue https://github.com/bazelbuild/rules_scala/issues/1056).
This can be worked around by building a fixed version of Jacoco yourselves (including backported fixes from 0.8.5) and reconfiguring your
build to use that one instead of the default jacocorunner
.
You can build jacocorunner with a script in scripts/build_jacocorunner/build_jacocorunner.sh
(see comments there for more explanation and options).
Then, you can use the jacocorunner
property of scala_toolchain
to provide the jacocorunner you have built:
# Example contents of coverage_local_jacocorunner/BUILD
scala_toolchain(
name = "local_jacocorunner_toolchain_impl",
jacocorunner = ":local_jacocorunner",
visibility = ["//visibility:public"],
)
toolchain(
name = "local_jacocorunner_scala_toolchain",
toolchain = "local_jacocorunner_toolchain_impl",
toolchain_type = "@io_bazel_rules_scala//scala:toolchain_type",
visibility = ["//visibility:public"],
)
filegroup(
name = "local_jacocorunner",
srcs = ["JacocoCoverage_jarjar_deploy.jar"],
)
In this example jacocorunner
is provided as a local file, but you could also upload your version to an artifactory and then use http_file
(to avoid
keeping binaries in your repository).
Finally provide the scala_toolchain
in your .bazelrc
or as an option to bazel coverage
:
coverage --extra_toolchains="//coverage_local_jacocorunner:local_jacocorunner_scala_toolchain"
You can verify that the locally built jacocorunner
works with manual_test/coverage_local_jacocorunner/test.sh
.