背景
Bazelでは次のようなディレクトリ構成で、
. ├── package_a │ ├── a.go │ ├── a_test.go │ └── test.yaml └── package_b ├── b.go └── b_test.go
パッケージAのファイルtest.yaml
をパッケージBのテストで参照したい時に、
go_test( name = "b_test", srcs = ["b_test.go"], deps = ["//path/to/package_a:package_a_lib"], data = ["//path/to/package_a"], )
としても、直接は参照できないです。
今回はその解決方法です。
環境
- Bazel v7.2.0
原因
参照できないときの主な原因は2つあります。
- 該当ファイルにvisibilityが設定されてないのでprivate扱いになっている
- Bazelのターゲットとして参照できるようになっていない
方法
対応方法は2種類あります。
exports_files
を使うfilegroup
を使って公開する
具体例
次のようなディレクトリ構造だとします。
. ├── BUILD.bazel ├── MODULE.bazel ├── MODULE.bazel.lock ├── Makefile ├── WORKSPACE ├── fizzbuzz │ ├── BUILD.bazel │ ├── fizzbuzz.go │ ├── fizzbuzz_test.go │ └── testdata │ └── golden.txt ├── fizzbuzz2 │ ├── BUILD.bazel │ ├── fizzbuzz.go │ └── fizzbuzz_test.go ├── go.mod └── go.sum
fizzbuzz2/fizzbuzz_test.go
ではfizzbuzz/testdata/golden.txt
を使いたいとします。
fizzbuzz2/fizzbuzz_test.go
自体は
package fizzbuzz2 import ( "os" "strings" "testing" ) func TestFizzBuzz(t *testing.T) { goldenFile := "../fizzbuzz/testdata/golden.txt" expectedOutput, err := os.ReadFile(goldenFile) if err != nil { t.Fatalf("failed reading golden file: %s", err) } expectedLines := strings.Split(string(expectedOutput), "\n") for i := 1; i < len(expectedLines); i++ { expected := expectedLines[i-1] actual := FizzBuzz(i) if actual != expected { t.Errorf("FizzBuzz(%d) = %s; want %s", i, actual, expected) } } }
と相対パスで参照しており、
$ go test ./... ok github.com/jun06t/bazel-sample/testfile/fizzbuzz ok github.com/jun06t/bazel-sample/testfile/fizzbuzz2
が通る状態ですが、そのままだとBazelでは以下のエラーが出ます。
//fizzbuzz:fizzbuzz_test PASSED in 0.5s //fizzbuzz2:fizzbuzz2_test FAILED in 0.3s
a. exports_files
exports_files
を使ってターゲットを用意する方法です。
fizzbuzz/BUILD.bazel
ファイルがある方のBUILD.bazelで、exports_filesを使ってファイルを参照可能にします。
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "fizzbuzz", srcs = ["fizzbuzz.go"], importpath = "github.com/jun06t/bazel-sample/testfile/fizzbuzz", visibility = ["//visibility:public"], ) go_test( name = "fizzbuzz_test", srcs = ["fizzbuzz_test.go"], data = ["testdata/golden.txt"], embed = [":fizzbuzz"], ) exports_files(["testdata/golden.txt"]) # ここ
fizzbuzz2/BUILD.bazel
ターゲットが公開されたら参照します。
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "fizzbuzz2", srcs = ["fizzbuzz.go"], importpath = "github.com/jun06t/bazel-sample/testfile/fizzbuzz2", visibility = ["//visibility:public"], ) go_test( name = "fizzbuzz2_test", srcs = ["fizzbuzz_test.go"], embed = [":fizzbuzz2"], data = ["//fizzbuzz:testdata/golden.txt"], # ここ )
動作確認
$ bazel test //... //fizzbuzz:fizzbuzz_test (cached) PASSED in 0.5s //fizzbuzz2:fizzbuzz2_test PASSED in 0.1s
通るようになりました。
b. filegroup
次はfilegroup
を使ってターゲットを用意する方法です。
fizzbuzz/BUILD.bazel
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "fizzbuzz", srcs = ["fizzbuzz.go"], importpath = "github.com/jun06t/bazel-sample/testfile/fizzbuzz", visibility = ["//visibility:public"], ) go_test( name = "fizzbuzz_test", srcs = ["fizzbuzz_test.go"], data = [":test_dir"], # ここ embed = [":fizzbuzz"], ) # ここ filegroup( name = "test_dir", srcs = glob(["testdata/**"]), visibility = ["//visibility:public"], )
exports_fileと違ってfilegroupは複数のファイルをまとめてターゲットに登録できます。
fizzbuzz2/BUILD.bazel
ターゲットが公開されたら参照します。
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "fizzbuzz2", srcs = ["fizzbuzz.go"], importpath = "github.com/jun06t/bazel-sample/testfile/fizzbuzz2", visibility = ["//visibility:public"], ) go_test( name = "fizzbuzz2_test", srcs = ["fizzbuzz_test.go"], embed = [":fizzbuzz2"], data = ["//fizzbuzz:test_dir"], # ここ )
動作確認
$ bazel test //... //fizzbuzz:fizzbuzz_test PASSED in 0.5s //fizzbuzz2:fizzbuzz2_test PASSED in 0.3s
その他
サンプルコード
今回のサンプルコードはこちら
まとめ
Bazelのテストで他パッケージのファイルを参照する方法を紹介しました。