エミュレータを使用した Spanner インテグレーション テスト
Google Cloud Japan Team
※この投稿は米国時間 2024 年 1 月 31 日に、Google Cloud blog に投稿されたものの抄訳です。
Spanner は、高いスケーラビリティと信頼性を備え、グローバルに分散された Google Cloud のデータベースです。優れたパフォーマンスと継続的運用が求められるビジネス クリティカルなアプリケーションに最適です。
デベロッパーは、アプリケーションに Spanner をシームレスに統合するために徹底的にテストを行う必要があります。インテグレーション テストは、システムのさまざまなコンポーネントに変更を加えた後に、それらのコンポーネントが連動するかの検証に重点を置いて行います。Spanner の場合、アプリケーションによるトランザクションやエラー処理などのデータ操作がデータベースと正しく連動するかをインテグレーション テストで確認します。
この投稿では、GitHub Action と Spanner エミュレータを使用して Spanner のインテグレーション テストの環境を設定する方法を紹介します。このエミュレータは Google Cloud 外で Spanner の動作を模倣するものです。Spanner データベースを活用するアプリケーションを迅速に開発するのに役立ちます。
テストするアプリケーションの例として、架空のゲームのプレイヤー プロファイルを管理する Golang のバックエンド サービスを使用します。これらで紹介する原則は、他の言語や業界の他のアプリケーションとサービスにも適用できます。
ここではプロファイル サービスと Spanner の間の「インテグレーション」をテストして、サービスへのコード変更が正しく動作するかどうかフィードバック ループを素早く獲得します。これは、スタック内のすべてのサービス間で行う完全なエンドツーエンドのテストではありません。エンドツーエンドのテストを行う場合は、本番環境へのデプロイ前に、Spanner を使用した実際のステージング環境を利用する必要があります。
ソフトウェア リリースの有効性を評価するために実施すべきテストの種類の概要については、こちらの投稿をご覧ください。
インテグレーション テストでは、以下のコンポーネントを使用します。
- GitHub Actions は、テストの実行を自動化するもので、コードが保存されているプラットフォームに組み込まれています。他の CI / CD プラットフォームも同様に動作します。
- Spanner エミュレータは、Spanner データベースの軽量のオフライン エミュレータです。
- プロファイル サービスは、Spanner に依存するアプリケーションです。
これらのコンポーネントの詳細は後述しますが、アーキテクチャは以下のようになります。


Spanner エミュレータを使用したプロファイル サービスのインテグレーション テスト
GitHub Actions: ワークフローの自動化
サービスコードが GitHub リポジトリに保存されているため、GitHub Actions が自動インテグレーション テストに最適なコンポーネントとなります。
GitHub Actions は、ソフトウェア開発のワークフローを自動化する継続的インテグレーションと継続的デリバリー(CI / CD)プラットフォームの一部です。GitHub リポジトリとシームレスに統合され、これによりコードの変更またはスケジュール設定されたイベントによってトリガーされる自動タスクを定義、実行できます。
Spanner エミュレータ: ローカルテスト環境
Spanner エミュレータは、完全オフラインで実行できる軽量なツールです。これにより、デベロッパーはクラウド費用を負担することも実際の Spanner インスタンスに依存することもなく、Spanner の利用を想定してアプリケーションをテストできます。これにより、迅速な開発サイクルとインテグレーションに関する問題の早期発見が容易になります。
Spanner エミュレータには、実際の Spanner データベースとは異なる点や制限事項がいくつかあり、これらを把握しておく必要があります。
プロファイル サービスのインテグレーション テストの環境設定
サンプルのゲーム アプリケーションのコードは GitHub にあります。最初にプロファイル サービスのインテグレーション テストを見てから、GitHub Action を使用して自動インテグレーション テストを実現するワークフローを見ていきます。
プロファイル サービスのインテグレーション テストは、プロファイル サービスの main_test.go ファイルにあります。このファイルは、以下のセクションにわかれています。
- Spanner エミュレータの起動
- スキーマと必要なテストデータを使用した Spanner インスタンスと Spanner データベースの設定
- プロファイル サービスの設定
- テスト自体
- テスト完了後のクリーンアップ
Spanner エミュレータの起動
Spanner エミュレータはコンテナとしてデプロイされるため、testcontainers-go ライブラリを使用します。これにより、Spanner エミュレータの起動を以下のとおり非常に簡単にコード化できます。
これにより、エミュレータ コンテナにポート 9010 がマッピングされ、これを使用して通信できるようになります。ネットワーキングでは Docker ネットワークを使用するため、そのネットワークにアクセスできるコンテナかプロセスであれば、「emulator」コンテナと通信できます。
testcontainers-go ライブラリを使用することで、コンテナの準備が完了するまで待機してから以降のステップに進みやすくなります。
コンテナの準備が完了したら、ホスト情報を取得してオペレーティング システムの環境変数として公開し、golang 構造体を定義します。これらはともに、後でインスタンスとデータベースを設定するときに使用します。
すべての準備が完了したら、以下のとおり Spanner のインスタンスとデータベースを作成できます。
Spanner のインスタンスとデータベースを設定する
エミュレータが動作している状態で、テスト用のインスタンスとデータベースを設定する必要があります。まず、以下のとおりインスタンスを設定します。
ここでは、Spanner インスタンスの golang ライブラリを使用してインスタンスを作成します。これは、先に SPANNER_EMULATOR_HOST 環境変数を設定している場合のみ機能します。それ以外の場合は、Spanner ライブラリが Google Cloud プロジェクトで動作している実際の Spanner インスタンスを探します。
ここで、インスタンスの準備が完了するまで待ってからテストに進みます。
データベース設定には、スキーマ ファイルが必要です。このスキーマ ファイルをどこから取得するかは、プロセスによります。この例では、Makefile での make profile-integration の手順でマスター スキーマ ファイルのコピーを作成します。これにより、プレイヤーのプロファイルに関連する最新のスキーマを取得できます。
データベースを設定するには、Spanner のデータベースの golang ライブラリを活用します。
この関数では、エミュレータが理解できるようにスキーマの変更を処理します。スキーマ ファイルを、末尾のセミコロンを除いたステートメントの配列に変換する必要があります。
データベースの設定が完了したら、プロファイル サービスを起動できます。
プロファイル サービスを起動する
ここで、プロファイル サービスを、エミュレータと通信できる別のコンテナ(testcontainers-go を使用)として起動します。
サービスの準備が完了したら、以下のとおりエンドポイント情報を取得して、テストで使用する構造体として公開します。
エミュレータとサービスの両方が動作している状態で、テストを実行できます。
テストの実行
このインテグレーション テストでは、testify assert ライブラリを使用して、プロファイル サービスのエンドポイントに到達します。サービスにより、以下の動作をテストします。
クリーンアップ
テストが実行されたら、作成したコンテナをクリーンアップします。これを行うには、teardown 関数を実行します。
ここでも、testcontainers-go のおかげで簡単にクリーンアップを行えます。
GitHub Actions のワークフロー
GitHub Actions の設定は、リポジトリの .github/workflows ディレクトリにワークフロー ファイルを追加するだけの簡単な処理です。
アクションの動作は、各ファイルの手順によって変わります。アクションを push リクエスト時にトリガーするか、それとも pull リクエスト時にトリガーするか。すべてのファイルに変更が発生した場合にアクションをトリガーするか、それとも一部のファイルの変更によってアクションをトリガーするか。アクションを実行するために、どのような依存関係を設定する必要があるでしょうか。
以下は、プロファイル サービスについて定義された YAML アクションです。
この単純な yaml ファイルでは、backend_services/profile ディレクトリの変更を含む pull リクエストがあった場合のみ動作するようタスクが定義されます。このアクションにより、Go の依存関係がインストールされ、何度かの lint チェックが実行されてから、単体テストとインテグレーション テストに移ります。
単体テストとインテグレーション テストの make コマンドは、リポジトリの Makefile で定義されています。
インテグレーション テストにより test_data/schema.sql ファイルが設定されています。
これにより、プロファイル サービスの変更に伴って pull リクエストが開かれると、インテグレーション テストはおおむね以下のようになります。




まとめ
Spanner エミュレータと GitHub Actions を活用することで、Spanner アプリケーション用の堅牢なインテグレーション テスト環境を設定できます。この手法により、開発工程の早い段階でインテグレーションに関する問題を検出、解決し、Spanner をアプリケーションにスムーズに統合できます。
Spanner の機能をより詳しく知りたい場合は、無料トライアル インスタンスをご利用ください。これを利用すると、90 日間無料で Spanner を試して、その特徴と機能を実際に体験できます。
ー デベロッパーリレーションズ エンジニア Derek Downey