首页 > 解决方案 > 集成 Go 和 Bazel 测试

问题描述

在我的 CI 系统中,我运行了各种 go 脚本来分析我的 Go 代码。例如,我有一个脚本可以验证各种主文件是否可以成功启动长时间运行的应用程序。为此,我通过运行 go 脚本go run startupvalidator -pkgs=pkg1,pkg2,pk3。我有兴趣使用 Bazel 来利用缓存来实现这一点,因为如果pkg1没有更改startupvalidator,就可以访问缓存pkg1,然后重新运行pkg2and pkg3

我想了几种不同的方法来做到这一点,但没有一个感觉是正确的。有没有“最好”的方法来实现这一点?这是 bazel 的合理用例吗?

我考虑过创建一个 bash 脚本,在其中运行类似:

go run startupvalidator $1

有一个BUILD.bazel文件包含

sh_binary(
  name = "startupvalidator-sh",
  sources = [":startupvalidator.sh"],
  deps = [
    "//go/path/to/startupvalidator",
  ],
)

我还考虑在BUILD.bazel文件中为每个pkg1,pkg2和放置一个类似的 sh_test ,pkg3以便我可以运行bazel run //go/pkg1:startupvalidator

但是,这实际上不起作用。有人对我应该如何处理这个问题有反馈吗?任何方向或指针表示赞赏。

标签: gobazel

解决方案


要利用缓存测试结果,您需要*_test使用bazel test. 也许您唯一缺少的部分是bazel run仅运行二进制文件(即使它是测试二进制文件),同时bazel test正在寻找最新的测试结果,这意味着它使用缓存?

您还需要拆分二进制文件,以便更改代码pkg2不会影响pkg1. 缓存中的操作键包括其所有输入文件的内容、正在运行的命令等。我不确定您startupvalidator是否将各种主要功能编译到其中,或者它是否在运行时查找二进制文件。如果它编译它们,您将需要构建单独的。如果它在运行时加载文件,请将它查找的文件放入data您的测试规则中,以便它们成为测试操作输入的一部分。

我会做这样的事情pkg1(假设它在运行时加载文件;如果它们被编译,那么你可以制作单独的go_test目标):

sh_test(
  name = 'startupvalidator_test',
  srcs = ['startupvalidator_test.sh'],
  deps = ['@bazel_tools//tools/bash/runfiles'],
  data = ['//go/path/to/startupvalidator', ':package_main'],
)

startupvalidator_test.sh看起来像:

# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
  source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
  source "$0.runfiles/$f" 2>/dev/null || \
  source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
  source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
  { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e

exec $(rlocation workspace/go/path/to/startupvalidator) \
  -main=$(rlocation workspace/pkg1/package_main)
# --- end runfiles.bash initialization v2 ---

我假设这package_main是由startupvalidator. Bazel 设置为将完整路径传递给其他二进制文件,所以我假装有一个新标志采用完整路径而不仅仅是包名。shell 脚本使用runfiles.bash来定位各种文件。

如果您想在包之间删除重复数据,我会编写一个使用genrule生成 shell 脚本的宏。


推荐阅读