このプロジェクトについて

# go-docker-testsuite Go製の統合テスト用ライブラリ。Dockerコンテナ内でサードパーティの依存関係を実行し、Goテストから接続できるようにする。データベース、キュー、キャッシュ、オブジェクトストレージなど、任意のDockerイメージを起動できる。 ## 機能 - **Container** — 任意のDockerイメージを作成、実行、出力待機、クリーンアップする低レベルラッパー - **Group** — 分離されたDockerネットワーク上で複数のコンテナをIPレベルで接続して実行 - **Applications** — 一般的なサービス(MySQL、PostgreSQL、Redis、Kafkaなど)向けの既製ラッパー - **Hooks** — コンテナごとのライフサイクルコールバック(BeforeRun、AfterRun、BeforeClose、AfterClose) - **Exec** — 実行中のコンテナ内でコマンドを実行し、stdout、stderr、終了コードを取得 - **ライフサイクルコマンド** — execによる起動時/準備完了後のコマンド実行 - **コンテナへのファイルコピー** — `WithFiles`で起動前にファイルをシード - **コンテナからのファイルコピー** — 実行中のコンテナからtarストリームとしてファイルを読み出し - **リソース制限** — CPU/メモリ/pidsを制限してホストとCIを保護 - **マッチャー** — 部分一致、完全一致、正規表現マッチャーでコンテナログを待機 - **待機戦略** — 合成可能な準備完了プローブ(ForLog、ForHTTPGet、ForCommand、ForTCPConnection) - **環境ビルダー** — 型付き環境変数のための流暢なDSL - **ポートバインディング** — ランダムまたは1対1割り当てによるDNATポートマッピング - **ネットワークモード** — ホストまたはカスタムネットワークのサポート - **IMAGE_PREFIX** — プロキシ/ミラー経由でイメージをルーティング - **`*testing.T`バインディング** — 安全な`t.Parallel()`による自動ティアダウンとロギング ## 要件 - Go 1.26以上 - 実行中のDockerデーモン(`DOCKER_HOST`経由でリモートホストでも動作) ## インストール マルチモジュールワークスペース:ルートがコアモジュールで、`applications/<name>`配下の各アプリケーションが独自のGoモジュール。必要なものだけを取得: ```sh go get github.com/teran/go-docker-testsuite # 特定のアプリケーションラッパー: go get github.com/teran/go-docker-testsuite/applications/redis go get github.com/teran/go-docker-testsuite/applications/postgres ``` ## アプリケーション 既製ラッパー(それぞれ型付きクライアントインターフェースを返し、起動、ヘルスチェック、クリーンアップを処理): - Ceph(RGW)+ AWS SDK v2 - ClickHouse + clickhouse-go - Forgejo + SQLite - FRRルーティングスイート + vtysh - K3s + client-go - Kafka + Sarama - Memcache + gomemcache - MinIO(S3互換) - MongoDB + mongo-driver - MySQL / MariaDB / Percona Server - NetBox + PostgreSQL + Redis - Nginx - OpenSearch + opensearch-go - Paperless-ngx + PostgreSQL + Valkey - PostgreSQL + pgx - Prometheus + prometheus/client_golang - RabbitMQ(AMQP + 管理API) - Redis + go-redis - ScyllaDB + gocql - Vault - Libvirtd(KVM/QEMU) 多くのパッケージにはpkg.go.devでテスト可能な例が含まれています。 ## 使用法 ### クイックスタート — MySQL ```go package main import ( "context" "database/sql" "time" _ "github.com/go-sql-driver/mysql" "github.com/teran/go-docker-testsuite/applications/mysql" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() app, err := mysql.New(ctx, "index.docker.io/library/mysql:8.0.4") if err != nil { panic(err) } defer app.Close(ctx) if err := app.CreateDB(ctx, "important_database"); err != nil { panic(err) } db, err := sql.Open("mysql", app.MustDSN("important_database")) if err != nil { panic(err) } defer db.Close() if _, err := db.ExecContext(ctx, "SELECT 1"); err != nil { panic(err) } } ``` ### マルチコンテナグループ ```go package main import ( "context" "time" "github.com/teran/go-docker-testsuite" "github.com/teran/go-docker-testsuite/wait" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() app := docker.NewApplication( c, docker.HookFunc(func(ctx context.Context, ht docker.HookType, c docker.Container) error { return wait.Wait(ctx, c, wait.ForLog(docker.NewSubstringMatcher("ready"))) }), ) g, err := docker.NewGroup("my-services", app1, app2) if err != nil { panic(err) } if err := g.Run(ctx); err != nil { panic(err) } defer g.Close(ctx) } ``` ### 待機戦略 ```go if err := wait.Wait(ctx, c, wait.ForHTTPGet(8080, wait.WithPath("/health"), wait.WithResponseStatuses(200), )); err != nil { panic(err) } ``` その他の戦略:`ForLog`、`ForCommand`、`ForTCPConnection`。`ForAll` / `ForAny` / `ForAtLeast`と組み合わせ可能。 ### `*testing.T`バインディング ```go func TestRedis(t *testing.T) { t.Parallel() c, err := docker.NewContainerWithT( t, "redis", images.Redis, nil, docker.NewEnvironment(), docker.NewPortBindings().PortDNAT(docker.ProtoTCP, 6379), ) if err != nil { t.Fatal(err) } c.RunT(ctx) // フェイルファスト;t.Cleanupを登録 } ``` ### ライフサイクルフック ```go docker.HookTypeBeforeRun // コンテナ起動前 docker.HookTypeAfterRun // コンテナ起動後 docker.HookTypeBeforeClose // コンテナ停止前 docker.HookTypeAfterClose // コンテナ停止後 ``` ### Execとライフサイクルコマンド ```go res, err := c.Exec(ctx, []string{"echo", "hello"}) if err != nil { panic(err) } if err := res.Error(); err != nil { panic(err) } fmt.Printf("exit code: %d\n", res.ExitCode) fmt.Printf("stdout: %s", res.Stdout) ``` ### コンテナへの/からのファイルコピー 小さなコンテンツには`FileFromBytes`を、大きなファイルには`io.Reader` + `Size`を`WithFiles`で使用。`docker.CopyFromContainer`でファイルを読み戻す。 ### イメージプレフィックス / プロキシ ```sh export IMAGE_PREFIX=registry-mirror.example.com ``` ## モジュールとリリース 単一バージョン番号のマルチモジュールワークスペースで、個別にタグ付け(例:コア`v1.6.0`、アプリケーション`applications/redis/v1.6.0`)。リリース順序:コアが先、次にアプリケーション。タグ付けにはMakefileを使用。 ## ライセンス Apache License, Version 2.0