このチュートリアルでは、Cloud Functions でビルドしたアプリのエンドツーエンドのテストを自動化する方法を学習します。Cloud Build がテスト パイプラインを実行し、HashiCorp Terraform がテストの実行に必要な Google Cloud リソースの設定と破棄を行います。Cloud Build トリガーは、コードが commit されるたびにパイプラインを開始します。
アプリの設計やアーキテクチャの選択を行う際は、テスト性を考慮する必要があります。アプリが正常に動作することを検証するには、包括的なテストセット(自動化された単体テスト、統合テスト、エンドツーエンド テストなど)を作成し、定期的にテストを行います。さまざまな Cloud Functions シナリオで各カテゴリのテストを行う方法については、テストのベスト プラクティスガイドをご覧ください。
単体テストは実行環境に依存しないため、通常は簡単に作成して実施できます。ただし、統合テストとシステムテストは複雑になります。特にクラウド環境では一層難しくなります。エンドツーエンドのシステムテストは、特に Cloud Functions などのサーバーレス テクノロジーを使用するアプリで必要になります。多くの場合、これらのアプリは疎結合のイベント ドリブンで、独立してデプロイされる場合もあります。Google Cloud の実行環境で関数がイベントに正しく応答しているかどうかを検証するには、包括的なエンドツーエンド テストが不可欠になります。
アーキテクチャ
次の図に、このチュートリアルで使用するコンポーネントを示します。
このアーキテクチャは、次のコンポーネントから構成されています。
build
プロジェクト。Cloud Build パイプラインをホストして実行します。test
プロジェクト。テスト中にサンプルアプリの Google Cloud リソースをホストします。- サーバーレス ウェブ パフォーマンス モニタリング チュートリアルで説明したアプリをサンプルアプリとして使用します。
- サンプルアプリの Google Cloud リソースは、ビルドのイテレーションごとに作成され、破棄されます。Firestore データベースは例外です。作成された後、以降のすべてのビルドで再利用されます。
目標
- Cloud Functions でビルドされたサンプルアプリの単体テストとエンドツーエンド テストを行う Cloud Build パイプラインを作成します。
- ビルドから Terraform を実行して、アプリに必要な Google Cloud リソースの設定と破棄を行います。
- 専用の Google Cloud テスト プロジェクトを使用してテスト環境を分離します。
- Cloud Source Repositories に Git リポジトリを作成し、commit 後にエンドツーエンドのビルドを開始する Cloud Build トリガーを追加します。
費用
このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。新しい Google Cloud ユーザーは無料トライアルをご利用いただけます。
このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳しくは、クリーンアップをご覧ください。
始める前に
-
Cloud プロジェクトを選択または作成します。これは、サンプルアプリをホストする
test
プロジェクトです。 test
プロジェクトの Google Cloud プロジェクト ID をメモします。この ID は、次の環境設定のセクションで必要になります。- プロジェクトでCloud Build、Cloud Functions、Cloud Source Repositories API を有効にします。
- Cloud Console で [Firestore] ページに移動します。 Firestore ページに移動
- Firestore データベースを作成します。
- 別の Google Cloud プロジェクトを選択または作成します。これは、Cloud Build パイプラインをホストする
build
プロジェクトです。 [リソースの管理] ページに移動 Google Cloud プロジェクトで課金が有効になっていることを確認します。
環境設定
このチュートリアルでは、Cloud Shell でコマンドを実行します。Cloud Shell はシェル環境です。gcloud
コマンドライン ツールなどの Cloud SDK がすでにインストールされており、現在のプロジェクトの値もすでに設定されています。Cloud Shell の初期化には数分かかることがあります。
Cloud Console で
build
プロジェクトに選択し、Cloud Shell を開きます。前の手順でコピーした
test
Google Cloud プロジェクト ID の変数を設定します。export TEST_PROJECT=your-test-project-id
次のように置き換えます。
your-test-project-id
:test
Google Cloud プロジェクトの ID。
現在の
build
Google Cloud プロジェクトのプロジェクト ID とプロジェクト番号を変数として設定します。export BUILD_PROJECT=$(gcloud config get-value core/project) export BUILD_PROJECT_NUM=$(gcloud projects list) \ --filter="$BUILD_PROJECT" --format="value(PROJECT_NUMBER)"
デプロイ リージョンの変数を設定します。
export REGION=us-central1
このチュートリアルでは
us-central1
リージョンを使用しますが、Cloud Functions を使用できる任意のリージョンに変更できます。このチュートリアルで使用するサンプルアプリのコードを格納するリポジトリのクローンを作成します。
git clone \ https://github.com/GoogleCloudPlatform/solutions-serverless-web-monitoring.git
プロジェクト ディレクトリに移動します。
cd solutions-serverless-web-monitoring
Terraform を使用したテスト インフラストラクチャの作成
このチュートリアルでは、Terraform を使用して、テスト プロジェクト内で Google Cloud リソースの作成と破棄を自動的に行います。ビルドごとに独立したリソースを作成すると、それぞれのテストを分離できます。テストを分離すると、ビルドが同時に行い、特定のリソースに対してテスト アサーションを行うことができます。各ビルドの最後にリソースを破棄することで、コストを最小限に抑えることができます。
このチュートリアルでは、サーバーレス ウェブ モニタリング チュートリアルで説明したアプリをデプロイします。このアプリは、Cloud Functions、Cloud Storage バケット、Pub/Sub リソース、Firestore データベースで構成されています。Terraform 構成では、これらのリソースの作成に必要な手順を定義します。Firestore データベースは Terraform によってデプロイされません。1 度作成したデータベースがすべてのテストで再利用されます。
Terraform 構成ファイル main.tf
の次のサンプルコードは、Cloud Functions trace
をデプロイするために必要な手順を示しています。完全な構成については、ファイル全体をご覧ください。
このステップでは、Terraform 構成を実行してテストリソースをデプロイします。これらのリソースは、後のステップで Cloud Build によって自動的にデプロイされます。
Cloud Shell で Terraform を初期化します。
docker run -v $(pwd):/app -w /app hashicorp/terraform:0.12.0 init
公開の Terraform Docker イメージを使用します。Docker は Cloud Shell にインストールされています。現在の作業ディレクトリはボリュームとしてマウントされるため、Docker コンテナは Terraform 構成ファイルを読み取ることができます。
Terraform の
apply
コマンドを使用してリソースを作成します。docker run -v $(pwd):/app -w /app hashicorp/terraform:0.12.0 apply \ --auto-approve \ -var "project_id=$TEST_PROJECT" \ -var "region=$REGION" \ -var "suffix=$TEST_PROJECT"
このコマンドには、テストリソースを作成する Google Cloud プロジェクトとリージョンを指定する変数が含まれています。また、このステップに名前付きのリソースを作成する際に使用される接尾辞も含まれています。後のステップで、Cloud Build が適切な接尾辞を自動的に指定します。
オペレーションが完了するまでに数分かかります。
test
プロジェクトにリソースが作成されたことを確認します。gcloud functions list --project $TEST_PROJECT
出力には、前に指定した接尾辞で終わる Cloud Functions が 3 つ表示されます。
エンドツーエンド テストの実施
このセクションでは、前のセクションでデプロイしたテスト インフラストラクチャにエンドツーエンドのテストを実施します。
次のコードスニペットでは、複数のテストを行っています。テストでは、成功と失敗の両方のシナリオを検証します。テスト パイプラインの概要は次のとおりです。
- まず、テストで
trace
関数を呼び出します。この呼び出しにより、他の機能をトリガーするアプリを介してイベントのフローが開始します。 - 次に、各関数の動作を検証します。オブジェクトが Cloud Storage に書き込まれ、結果が Firestore に格納され、Pub/Sub アラートが生成されたことを確認します。
エンドツーエンド テストを実施するには、次の操作を行います。
Cloud Shell で、新しい
virtualenv
環境を作成します。virtualenv
ユーティリティは、すでに Cloud Shell にインストールされています。virtualenv venv
virtualenv
環境を有効にします。source venv/bin/activate
必要な Python ライブラリをインストールします。
pip install -r requirements.txt
エンドツーエンド テストを開始します。
python -m pytest e2e/ --tfstate terraform.tfstate
Terraform 状態ファイルを渡します。このファイルには、前のセクションで作成したテストリソースの詳細が含まれています。
テストが完了するまでに数分かかることがあります。2 つのテストに合格したことを示すメッセージが表示されます。警告は無視してかまいません。
Terraform の
destroy
コマンドを使用して、テストリソースを破棄します。docker run -v $(pwd):/app -w /app hashicorp/terraform:0.12.0 destroy \ --auto-approve \ -var "project_id=$TEST_PROJECT" \ -var "region=$REGION" \ -var "suffix=$TEST_PROJECT"
リソースが破棄されたことを確認します。
gcloud functions list --project $TEST_PROJECT
前に指定した接尾辞で終わる Cloud Functions はなくなりました。
Cloud Build パイプラインの送信
このセクションでは、Cloud Build を使用してテスト パイプラインを自動化します。
Cloud Build の権限を設定する
Cloud Build サービス アカウントを使用して Cloud Build を実行します。ビルドによって実行されるシステムテストでは、Cloud Functions、Cloud Storage バケット、Pub/Sub リソース、Firestore ドキュメントを作成して操作します。これらの処理を行うには Cloud Build に以下のものが必要です。
- テスト プロジェクトに対する適切な Identity and Access Management(IAM)ロール。
- Cloud Functions ランタイム サービス アカウントとしての権限。デフォルトでは、Cloud Functions は App Engine サービス アカウント(
your-test-project-id@appspot.gserviceaccount.com
)をランタイム サービス アカウントとして使用します。ここで、your-test-project-id
はtest
Google Cloud プロジェクトの名前です。
この手順では、適切なロールを追加してから、Cloud Build サービス アカウントを追加します。
Cloud Shell で、適切な IAM ロールをデフォルトの Cloud Build サービス アカウントに追加します。
for role in cloudfunctions.developer pubsub.editor storage.admin datastore.user; do \ gcloud projects add-iam-policy-binding $TEST_PROJECT \ --member="serviceAccount:$BUILD_PROJECT_NUM@cloudbuild.gserviceaccount.com" \ --role="roles/$role"; \ done
テスト プロジェクトの App Engine サービス アカウントの
serviceAccountUser
として、Cloud Build サービス アカウントを追加します。gcloud iam service-accounts add-iam-policy-binding \ $TEST_PROJECT@appspot.gserviceaccount.com \ --member="serviceAccount:$BUILD_PROJECT_NUM@cloudbuild.gserviceaccount.com" \ --role=roles/iam.serviceAccountUser \ --project $TEST_PROJECT
手動ビルドの送信
ビルドでは次の 4 つの論理タスクを実行します。
- 単体テストの実施
- サンプルアプリのデプロイ
- エンドツーエンド テストの実施
- サンプルアプリの破棄
cloudbuild.yaml
ファイルの次のコードスニペットを見てみましょう。このスニペットは、Terraform を使用してサンプルアプリをデプロイし、エンドツーエンド テストを実行する個々の Cloud Build ステップを示しています。
手動ビルドを Cloud Build に送信し、エンドツーエンド テストを実施するには、次の操作を行います。
Cloud Shell で、次を入力します。
gcloud builds submit --config cloudbuild.yaml \ --substitutions=_REGION=$REGION,_TEST_PROJECT_ID=$TEST_PROJECT
ビルドの実行には数分かかります。次のビルドステップが実行されます。
Cloud Build が、置換を使用して、作成するテストリソースの Google Cloud プロジェクトとリージョンを指定します。
Cloud Build が
build
Google Cloud プロジェクトでビルドを実行します。テストリソースは別のtest
プロジェクトに作成されます。
ビルドログが Cloud Shell にストリーミングされるため、ビルドの進行状況を追跡できます。ログのストリーミングはビルドの完了時に終了します。最後の
terraform-destroy
ビルドステップが成功し、ビルドの完了を通知するメッセージが表示されます。
テストの自動化
継続的インテグレーション(CI)の基本原則は、一連の包括的な自動テストを定期的に行うことです。通常、ビルドテスト パイプラインは、共有コード リポジトリへの commit ごとに実行されます。これにより、共有リポジトリに対する各 commit がテストおよび検証され、チームが問題を早期に検出できるようになります。
以降のセクションでは、次の操作を行います。
- Cloud Source Repositories に Git リポジトリを作成する。
- commit ごとにエンドツーエンドのビルドを実行するように Cloud Build トリガーを追加する。
- コードをリポジトリに push してビルドをトリガーする。
Cloud Source Repositories のリポジトリと Cloud Build トリガーを作成する
Cloud Shell で、新しい Cloud Source Repositories のリポジトリを作成します。
gcloud source repos create serverless-web-monitoring
Cloud Console で、Cloud Build の [トリガー] ページを開きます。
[トリガーを作成] をクリックします。
[トリガーの作成] ページが開きます。
次のオプションを入力します。
- [名前] フィールドに
end-to-end-tests
と入力します。 - [イベント] で [ブランチに push する] を選択します。
- [ソース] で、[リポジトリ] として
severless-web-monitoring
を選択し、[ブランチ] として^master$
を選択します。 - [ビルド構成] で [Cloud Build 構成ファイル] を選択します。
- [Cloud Build 構成ファイルの場所] フィールドに「
cloudbuild.yaml
」と入力します。 変数置換を追加して、テストリソースを作成する Google Cloud リージョンを指定するには、[変数を追加] をクリックします。
- 変数:
_REGION
値:
your-test-region
次のように置き換えます。
your-test-region
: Cloud Shell の$REGION
変数の値。
- 変数:
別の変数置換を追加して、テストリソースをホストするプロジェクトの ID を指定するには、[変数を追加] をクリックします。
- 変数:
_TEST_PROJECT_ID
値:
your-test-project
次のように置き換えます。
your-test-project
: Cloud Shell の$TEST_PROJECT
変数の値。
- 変数:
- [名前] フィールドに
[作成] をクリックして、ビルドトリガーを保存します。
ビルドを開始する
Cloud Shell で、新しいリモートとしてリポジトリを git config に追加します。
git remote add csr \ https://source.developers.google.com/p/$BUILD_PROJECT/r/serverless-web-monitoring
ビルドをトリガーするには、コードをリポジトリに push します。
git push csr master
最新のビルドを一覧表示します。
gcloud builds list --limit 3
出力で、ビルドのステータスが
WORKING
と表示されていれば、ビルドが想定どおりにトリガーされています。次のステップで使用するため、
WORKING
ビルドの ID をコピーします。ビルドログを Cloud Console にストリーミングします。
gcloud builds log --stream
build-id
次のように置き換えます。
build-id
: 前の手順でコピーしたWORKING
ビルドの ID。
ログのストリーミングはビルドの完了時に終了します。最後の
terraform-destroy
ビルドステップが成功し、ビルドの完了を通知するメッセージが表示されます。
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
プロジェクトの削除
- Cloud Console で [リソースの管理] ページに移動します。
- プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
- ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。
次のステップ
- Google Cloud CI / CD デベロッパー ハブにアクセスする。
- ブログ投稿で、テストと CI / CD で本番環境でのバグを回避する方法を確認する。
- 関連するサーバーレス ウェブ モニタリングのチュートリアルを行う。
- Cloud Build を使用した GitOps スタイルの継続的デリバリーのチュートリアルを行う。
- Terraform を使用して Google Cloud プロジェクトを管理する方法を確認する。
- Google Cloud のその他の機能を試す。チュートリアルをご覧ください。