Skip to content

Commit

Permalink
Save test coverage data to bazel-testlogs. (#1387)
Browse files Browse the repository at this point in the history
This lets `bazel coverage //some:test` produce a Go coverage data file
in `bazel-testlogs/some/test/coverage.dat`. This file can be processed
by normal Go coverage tooling to produce a coverage report.

The change to `go/private/rules/test.bzl` needs some explanation --
Bazel only looks for coverage data if the test target has an
`InstrumentedFilesProvider`, but this provider can currently only be
created using "legacy" provider syntax. Old and new provider syntaxes
can be combined by putting new-style providers in a `providers` field
of the old-style struct.

If the provider is found and at least one source file is present, Bazel
will set the `COVERAGE_OUTPUT_FILE` environment variable during tests
and will save that file to the build events + test outputs.
  • Loading branch information
jmillikin-stripe authored and jayconrod committed Mar 16, 2018
1 parent 2d33362 commit 6a2a5c5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 6 deletions.
29 changes: 23 additions & 6 deletions go/private/rules/test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,30 @@ def _go_test_impl(ctx):

runfiles = ctx.runfiles(files = [executable])
runfiles = runfiles.merge(test_archive.runfiles)
return [
DefaultInfo(
files = depset([executable]),
runfiles = runfiles,
executable = executable,

# Bazel only looks for coverage data if the test target has an
# InstrumentedFilesProvider, but this provider can currently only be
# created using "legacy" provider syntax. Old and new provider syntaxes
# can be combined by putting new-style providers in a providers field
# of the old-style struct.
# If the provider is found and at least one source file is present, Bazel
# will set the COVERAGE_OUTPUT_FILE environment variable during tests
# and will save that file to the build events + test outputs.
return struct(
providers = [
DefaultInfo(
files = depset([executable]),
runfiles = runfiles,
executable = executable,
),
],
instrumented_files = struct(
extensions = ['go'],
source_attributes = ['srcs'],
dependency_attributes = ['deps', 'embed'],
),
]
)


go_test = go_rule(
_go_test_impl,
Expand Down
6 changes: 6 additions & 0 deletions go/tools/builders/generate_test_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ func main() {
testing.RegisterCover(coverage)
}
if coverageDat, ok := os.LookupEnv("COVERAGE_OUTPUT_FILE"); ok {
if testing.CoverMode() != "" {
flag.Lookup("test.coverprofile").Value.Set(coverageDat)
}
}
m := testing.MainStart(testdeps.TestDeps{}, testsInShard(), benchmarks, examples)
{{if not .TestMain}}
os.Exit(m.Run())
Expand Down
4 changes: 4 additions & 0 deletions tests/legacy/coverage/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ bazel_test(
if ! grep -q '^coverage: 50.0% of statements' "bazel-testlogs/$RULES_GO_OUTPUT/go_default_test/test.log"; then
echo "error: no coverage output found in test log file" >&2
exit 1
fi
if ! grep -q 'io_bazel_rules_go/tests/legacy/coverage/lib.go:' "bazel-testlogs/$RULES_GO_OUTPUT/go_default_test/coverage.dat"; then
echo "error: no coverage data found in bazel-testlogs"
exit 1
fi
""",
command = "coverage",
Expand Down

0 comments on commit 6a2a5c5

Please sign in to comment.