ローカル実行によるデバッグとテスト
アプリケーションコードをローカル開発環境で実行しデバッグを行う方法とテストの方法を記載したドキュメントです。
概要
AWS Lambda は Amazon API Gateway 起動(Web API)でも Event 起動でも同じく handler 関数の第一引数 event
に処理に必要なデータが入っています。この Event Payload をあらかじめ作成してローカル実行ることで Lambda の動きを再現します。
処理の中で Amazon DynamoDB や S3 など他の AWS サービスと連携する場合は、AWS Lambda 実行ロールの代わりにローカル環境にセットされている AWS 認証情報( 環境変数のアクセスキー または ~/.aws/credentials
)が利用されます。docker-compose で minio, dynamodb-local を起動していて AWS SDK にそれらのエンドポイントが記載されている場合、それらのコンテナに接続されます。
以下よりイベントペイロードを指定する例を確認いただけます。
-
WebAPI ロジック
- API Gateway (REST API) から渡されるAPI呼び出しのリクエストペイロードを直接指定する形で、API ルーティングライブラリのインターフェースに合わせ、ハンドラー関数を実行しています。
.local/sample-api/get-users.ts
.local/sample-api/post_users.ts
- API Gateway (REST API) から渡されるAPI呼び出しのリクエストペイロードを直接指定する形で、API ルーティングライブラリのインターフェースに合わせ、ハンドラー関数を実行しています。
-
Event 起動
- S3・SNS・SQSなどから渡されるイベントペイロードを直接指定し、ハンドラー関数を実行しています。
.local/sample-event/post-s3-event.ts
- S3・SNS・SQSなどから渡されるイベントペイロードを直接指定し、ハンドラー関数を実行しています。
イベントペイロードのテンプレートは、AWS Lambda のコンソールから取得できます。S3 イベントの場合「S3 Put」、API Gateway (REST API) の場合は「API Gateway AWS Proxy」を選択してください。
ローカル実行の手順
※「ローカル環境」とは、本カタログで立ち上げた EC2 インスタンスの環境を指します。
1. Dockerの立ち上げ
ローカル開発は専用のpythonスクリプトと、PostgreSQLのコンテナ及びS3の互換ストレージであるMinIOのコンテナを使って行います。まずはdocker-compose.yamlに定義されているこれらのコンテナを起動しましょう。
[ec2-user ~] docker compose up -d
2. DBセットアップ(Table作成)
コンテナで起動したPostgreSQL内にデータベースとテーブルを作成します。以下のPythonスクリプトでデータベースとusersテーブルをコンテナ内に自動作成してくれます。
[ec2-user ~] npx tsx .local/setup-db.ts
一方、スクリプトを利用せず、直接 psql という PostgreSQL のコマンドラインツールもインストール済みなのでそれを使ってコンテナ内のテーブルの操作を行うことも可能です。ここでは3件データを作成しています。パスワードが求められますが、password
と入力してください。
[ec2-user ~]psql -h localhost -U admin -d mydb
mydb=# INSERT INTO users (name, country, age) VALUES
('Alice', 'Japan', 30),
('Bob', 'USA', 25),
('Charlie', 'Germany', 35);
mydb=# exit #これで通常のターミナルに戻れます
3. APIのローカル実行
GETのAPI
.local/sample-api/get-users.ts
はGETメソッドでユーザデータを取得するAPIをシュミレートしたスクリプトです。ファイル内のリクエスト作成箇所を変更しながらデバッグや動作確認が可能です。
// Dynamic import after environment variables are set
const { api } = await import('../../src/sample-api')
// Test user ID - change this value to test different cases
const userId = 1
const response = await api.app.request(`/v1/users/${userId}`, {
method: 'GET',
})
const body = await response.json()
[ec2-user ~] npx tsx .local/sample-api/get-users.ts
API Execution Result: {"statusCode": 200, "body": "{\"statusCode\":200,\"body\":{\"name\":\"Alice\",\"country\":\"Japan\",\"age\":30}}", "isBase64Encoded": false, "headers": {"Content-Type": "application/json"}, "cookies": []}
実際にスクリプトを走らせるとAPIからのレスポンスが返ってきます。
POSTのAPI
.local/sample-api/post_users.ts
はPOSTメソッドでユーザを作成するAPIをシュミレートします。今回は以下Bodyパラメータを操作しながら開発が可能です。
// Dynamic import after environment variables are set
const { api } = await import('../../src/sample-api')
// Test data - change this to test different cases
const userData = {
name: 'Hanako',
country: 'Japan',
age: 25,
}
const response = await api.app.request('/v1/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData),
})
const body = await response.json()
実際にスクリプトを実行すると正しくBodyに設定されたデータが作成されていることが分かります。
[ec2-user ~] npx tsx .local/sample-api/create-users.ts
API Execution Result: {"statusCode": 200, "body": "{\"statusCode\":200,\"body\":{\"message\":\"The data created successfully.\"}}", "isBase64Encoded": false, "headers": {"Content-Type": "application/json"}, "cookies": []}
$ mydb=# SELECT * FROM users WHERE id=4;
id | name | country | age
----+--------+---------+-----
4 | Shigeo | Japan | 30
(1 row)
4. S3イベントのローカル実行
S3イベントではMinIOというS3互換ストレージを使ってテストします。以下スクリプトを実行するとMinIO上にtest-bucketというバケットを作成して、sample_users.csvをアップロードします。
[ec2-user ~] npx tsx .local/setup-minio.ts
MinIOでは直接Lambdaをトリガーするところまでは再現できません。なので、.local/sample-event/process-s3-event.ts
でLambdaがトリガーされた時のイベントを生成し、ローカル実行を可能としています。スクリプトを実行するとsample_users.csvの内容がDB内に生成されていることが分かります。
[ec2-user ~] npx tsx .local/sample-event/process-s3-event.ts
mydb=# SELECT * FROM users;
id | name | country | age
----+---------+---------+-----
1 | Alice | Japan | 30
2 | Bob | USA | 25
3 | Charlie | Germany | 35
4 | Shigeo | Japan | 30
5 | Taro | Japan | 30
6 | Alice | USA | 28
7 | Bob | UK | 35
8 | Maria | Germany | 25
9 | Li | China | 32
5. ユニットテスト
ユニットテストもサンプルの実装を提供しています。pytestを使って、testsディレクトリの配下にテストコードが配置されています。ユニットテストも同様にPostgreSQLとMinIOのコンテナを使って、バリデーションのパターンや正常系のパターンなど必要と思われるテストケースを実装しています。
テストは以下のコマンドで実行できます。
[ec2-user ~] npm run test
その他のテスト方法
ローカル環境で擬似的な環境を立ち上げる
WebAPI ロジックの場合、SAM Local ( start-api
) を利用して localhost にて Amazon API Gateway をエミュレーションした API サーバーを立ち上げることが可能です。
- SAM Local (SAM CLI)
Event 起動の場合、以下のようなものでローカル環境で AWS サービスをエミュレーションしてテスト等を行うことが可能です。
-
Amazon S3
- MinIO(※ OSS版での利用が可能)
-
Amazon DynamoDB
- DynamoDB Local(※AWSが配布する公式ツール)