Testcontainers for Go を使ってみる
これを試してみます。
手元のDocker環境はcolimaを利用しています。
docker version
Client: Docker Engine - Community
Version: 23.0.1
API version: 1.41 (downgraded from 1.42)
Go version: go1.19.5
Git commit: a5ee5b1dfc
Built: Thu Feb 9 19:15:59 2023
OS/Arch: darwin/arm64
Context: default
Server:
Engine:
Version: 20.10.11
API version: 1.41 (minimum version 1.12)
Go version: go1.16.4
Git commit: 847da184ad5048b27f5bdf9d53d070f731b43180
Built: Wed Apr 13 23:41:08 2022
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: v1.5.8
GitCommit: 1e5ef943eb76627a6d3b6de8cd1ef6537f393a71
runc:
Version: 1.0.0-rc95
GitCommit: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
docker-init:
Version: 0.19.0
GitCommit:
Colimaで利用するにはいくつか環境変数を設定しておく必要がありそう。
以下は参考にしたページ。
.zshrc
に以下を書いたら良さそうか。
# testcontainers
export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
export TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE="/var/run/docker.sock"
TESTCONTAINERS_RYUK_DISABLED
はあってもなくても動いた。
ひとまず細かい動作の違いは見ていない。
VSCodeのUI上からテストコードを実行しようとすると環境変数が適用されてなさそうなのはどうすれば良いか?
.vscode/launch.json
に記載するというのもあるが二重管理だしなんかそれじゃない感がある。
{
"name": "Launch Program",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${fileDirname}",
"env": {
"DOCKER_HOST": "unix:///Users/xxxxx/.colima/default/docker.sock",
"TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE": "/var/run/docker.sock",
"TESTCONTAINERS_RYUK_DISABLED": "true",
},
"args": [
"-test.v",
"-test.run",
"TestYourFunc"
],
}
VSCode自体を一度終了させて起動したら反映されたぽいがそれしか方法ないのかな?
なかなか動かなくて時間を溶かしたし、動いたことに達成感を得たが本題はPostgreSQLにデータ投入してテストを書くことだった。
まずはExampleを眺める。
初期データは test/dbdata
にsqlファイル置いて /docker-entrypoint-initdb.d
としてマウントさせれば取り込まれてそう。
func NewTestDatabase(t *testing.T) *TestDatabase {
initdbDir, _ := filepath.Abs("../../test/dbdata")
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
defer cancel()
req := testcontainers.ContainerRequest{
Image: "postgres:14",
ExposedPorts: []string{"5432/tcp"},
AutoRemove: true,
Env: map[string]string{
"POSTGRES_USER": "user",
"POSTGRES_PASSWORD": "password",
"POSTGRES_DB": "testdb",
},
Mounts: testcontainers.ContainerMounts{
testcontainers.BindMount(initdbDir, "/docker-entrypoint-initdb.d"),
},
WaitingFor: wait.ForListeningPort("5432/tcp").WithStartupTimeout(time.Minute * 2),
}
postgres, err := testcontainers.GenericContainer(
ctx,
testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
},
)
require.NoError(t, err)
return &TestDatabase{
instance: postgres,
}
}
/docker-entrypoint-initdb.d
に置いたファイルはファイル名でソートして昇順に実行されるらしい。
prefixに 0001_
, 0002_
などとつけておけば複数ファイルを置いても意図した順番で実行できそう。
サポートされているファイルは .sh
, .sql
, .sql.gz
dockertest はColimaと使うにはシンボリックリンク貼れって感じなのか
テストが途中でコケたり通ったりする場合はタイムアウトしていることがあるので確認してタイムアウト値を伸ばしましょう
現状はこんな感じのオプションでテスト実行している
go test -timeout 180s -short -race ./...
個人的な結論としてはTestcontainers for Goは結構良さそうで、全パターン網羅するようなテストを書くかは置いておいて、クエリ書く時に関数単位ですぐに動かして試せる環境を持てるのが良いと思う。
Testcontainersを使ったテストをすぐ動かせるやつ作った