はじめに
みなさんこんにちは ! AWS の 高野 賢司 です。最近、子どものために買った電子ピアノで自分も練習しはじめました。2025 年の目標は「毎日 15 分でいいから練習を継続する」です。なお音楽センスはまったくないので、弾けるようになることはつゆほども期待していません。
シリーズ『AWS CDK で試して学ぶ サーバーレス開発の達人の技』では、インフラからアプリまでさまざまな領域の「達人」にインタビューして、開発高速化のための「達人の技」を AWS CDK を使って試していきます。
ではさっそく、今回のトピックを紹介します。
💭 AWS Lambda 関数の動きを確認するのに、デプロイするのがちょっと面倒・・・
前回の記事 では、AWS CDK を使用して Lambda 関数をサクッとデプロイしました。ホットスワップ機能を利用すれば数秒から数十秒で関数をデプロイできますし、 cdk watch コマンドで変更されたファイルの監視やログの確認もできます。
でも、Lambda 関数の中身のロジックを 1 行変更しただけで動作確認に数秒待たされると思うと、ちょっと長すぎますよね。
ということで今回は、新しいアプリをゴリゴリ生み出す達人、AWS Prototyping Engineer の 工藤 朋哉 さんに「最短で Lambda 関数の動きを確認する技」を教えてもらいましょう !
本記事は、アプリケーションコードをあまり書いたことがないインフラエンジニアやサーバーレス開発の初心者、テスト自動化に馴染みがないアプリエンジニアを対象とした内容となっています。テスト自動化へのモチベーションを高めるため、導入部分ではベストプラクティスに沿わない部分があることをご容赦ください。
builders.flash メールメンバー登録
Lambda 関数の検証時間はどうすれば短くなる ?
工藤「デプロイ回数が多いと辛いですよね。どんな検証をしているんですか ?」
高野「 admin ロールをもつユーザーを返す関数を Python で作っているんですが、取得漏れや余分なユーザーが含まれるバグがないか気になっていて・・・。」
backend/src/app.py ... Lambda ハンドラーのコード
コード
USERS = [
{"username": "foo", "roles": []},
{"username": "bar", "roles": ["admin"]},
{"username": "baz", "roles": ["audit"]},
{"username": "qux", "roles": ["admin", "audit"]},
]
def handler(event, context):
# admin ロールを保持しているユーザーだけを返す
users = [user for user in USERS if "admin" in user["roles"]]
return {"statusCode": 200, "body": users}
bin/cdk.ts ... CDK のコード
コード
new Function(this, "ListUsersFunction", {
runtime: Runtime.PYTHON_3_13,
handler: "src/app.handler",
code: Code.fromAsset("backend"),
});
Lambda 関数のコードはローカルで直接実行可能
高野「これを cdk watch でデプロイして、aws lambda invoke コマンドで動かしています。」
工藤「なるほど。確認したいのはビジネスロジックなのに、デプロイで余計な待ち時間が発生しているんですね。じゃあ、直接 app.py を実行しちゃうのはどうでしょうか。」
高野「えっ、Lambda 関数のコードってローカルで直接実行できるんですか?クラウドにデプロイするか、エミュレータみたいなものが必要だと思っていました。それにほら、 event とか context という謎の引数が渡されていますよ。」
工藤「Lambda 関数のコードはただの Python コードなので実行できますよ。実際に Lambda サービスの中でも handler() のように呼び出しているだけで、特別なことはしていません。ハンドラーの引数は、いまは関数の中で参照していないですよね。必要になったら必要な分だけ渡せばいいんです。とりあえず動かしてみましょう。」
Note : Lambda の中でハンドラー関数がどのように実行されているか詳しく知りたい方は、こちらの記事 の bootstrap ファイルを見てみることをおすすめします。
達人の技 1 / ローカル実行用のスクリプトで動作確認する
✨️技の効果:検証時間を短くする
Lambda ハンドラーのローカル実行スクリプトを作成
Python と TypeScript で、Lambda ハンドラーのローカル実行スクリプトを書いてみましょう。
Python
main.py ... Lambda ハンドラーを直接実行するためのスクリプト
from pprint import pprint # レスポンスの整形表示用
from app import handler
def main():
response = handler({}, {})
pprint(response)
if __name__ == "__main__":
main()
実行方法
python main.py
TypeScript
⚠️ ts-node のインストールが必要です。 npm i -D ts-node
⚠️ any 型の使用に抵抗がある方は続きをお読みください !
app.ts ... Lambda ハンドラーのコード
type User = {
username: string;
email: string;
roles: string[];
};
const Users: User[] = [
{ username: "foo", roles: [] },
{ username: "bar", roles: ["admin"] },
{ username: "baz", roles: ["audit"] },
{ username: "qux", roles: ["admin", "audit"] },
];
export const handler = async function (event: any, context: any) {
const users = Users.filter((user) => user.roles.includes("admin"));
return { statusCode: 200, body: JSON.stringify(users) };
};
main.ts ... Lambda ハンドラーを直接実行するためのスクリプト
import { handler } from "./app";
async function main() {
const response = await handler({}, {});
console.log(response);
}
main();
実行方法
npx ts-node main.ts
ハンドラー関数の引数は ?
高野「ローカルで Lambda ハンドラーが実行できるのは便利ですね ! 時間短縮になりました。でもやっぱり、ハンドラーの引数で実際にどんな値が渡されるのか気になります。TypeScript で any 型を使うのも気が引けますし・・・。」
工藤「event や context の内容が重要なときは、実際にクラウド上で動かしてイベントをキャプチャするか、生成 AI に聞くのがおすすめです。」
達人の技 2 / 生成 AI に引数を補完してもらう
✨️技の効果:コードを時間を短くする。複雑な型が必要なときに特に有効
ハンドラーにどんな引数が渡されるかわからない場合は、生成 AI にサンプルコードを書いてもらうのが有効です。静的型付けの言語でのエラー解決だけでなく、値まで書いてくれるのがメリットです。
Lambda ハンドラーの定義
例えば、TypeScript で Amazon API Gateway のプロキシ統合を使用した Lambda ハンドラー はこのように定義できます。
export const handler: APIGatewayProxyHandler = async function (event, context) {
const users = Users.filter((user) => user.roles.includes("admin"));
return { statusCode: 200, body: JSON.stringify(users) };
};
npm パッケージをインストール
handler に指定されている型の定義は @types/aws-lambda パッケージで提供されています。npm パッケージをインストールするには以下のコマンドを実行します。詳細は「TypeScript の Lambda 関数ハンドラーの定義」を参照してください。
npm i -D @types/aws-lambda
ハンドラー関数の型情報
IDE でマウスオーバーしてハンドラー関数の型情報をみてみると、APIGatewayProxyEvent などを引数に取ることがわかります。

Amaozn Q Developer のインラインチャット
コーディング中に生成 AI を使う方法はいくつかあります。チャット形式で「これは AWS Lambda のハンドラー関数です。ローカルの Node.js で呼べるようにするコードを書いてください」と聞いてみるのもいいでしょう。
エンジニアであれば、IDE の中でコードを直接修正してもらったほうが便利ですよね。Amaozn Q Developer のインラインチャット を使えば、ピンポイントで APIGatewayProxyEvent や Context 型のオブジェクトを生成してくれます。次のようにコンパイルエラーになっている状態で Control + I (macOS の場合は Command + I) を押して次のようなプロンプトを入力します。
Fix type errors. Fill required fields in each interface with sample values

サンプル値を入力
すると、インターフェースを充足するようにフィールドを追加し、それっぽいサンプル値を入れてくれます。便利ですね !
💡 Tips : AWS の認証情報があれば API 呼び出しも可能
ローカルでのスクリプト実行時に AWS の認証情報を環境変数などにセットしていれば、AWS SDK を使用したコードの実行も可能です。ベストプラクティスとして、永続的な IAM ユーザーのアクセスキーではなく、AWS IAM Identity Center で認証情報を取得することをおすすめします。詳細は AWS CLI のドキュメント を参照してください。
ただし、持っている権限によってはデータやリソースの変更ができてしまうため、副作用に注意して使用してください。

テストを自動化してもっと楽をしよう
工藤「ローカル実行はあくまで、とりあえず動かすための手段です。今回でいえばユーザーの抽出ロジックが肝ですが、 狙ったところだけ、すばやく、何回も結果を確認するには、テストを自動化しちゃいましょう。」
高野「でも、テスト自動化って難しいんでしょう? テストピラミッドとか、モックとか言われてもよくわかりません !」
工藤「自動化されたテストでやることはさっきのローカル実行とあまり変わりませんよ。コードを実行して、結果を検証する部分を自動にするだけです。つまり、 ただの便利スクリプトの一種です。まずはユニットテストといって、純粋な Python コードだけで完結する部分のテストを書いてみましょう。」
達人の技 3 / 便利スクリプトとしてのユニットテストを書こう
✨️技の効果:検証時間を短くする。コードを変更したとき、意図しない部分が壊れていないか確認してエンジニアの心を安らげる
Python のテストフレームワークである pytest をインストールするために、Python の仮想環境を作成します。
Note: pytest は Lambda の デプロイパッケージ (ソースコードや依存パッケージを zip にまとめたもの) には必要ないため、通常の requirements.txt ではなく requirements-dev.txt に保存しています。
Note : TypeScript で Lambda 関数のコードを記述する場合、テストフレームワークには Jest がよく使用されます。Lambdaのデプロイパッケージを作成するには、NodejsFunction コンストラクトを使用すると便利です。NodejsFunction はコードを自動的に esbuild でバンドルして不要な依存関係やコードを取り除いてくれるため、CDK アプリと同じ package.json で依存関係管理できます。
Python の仮想環境を作成
コマンド
cd backend
python3 -m venv .venv
source .venv/bin/activate
echo pytest >> requirements-dev.txt
pip3 install -r requirements-dev.txt
メインのロジックを新しい関数に分離
src/app.py をテストをしやすくするために、ハンドラー関数からメインのロジックを新しい関数に分離します。これで filter_users_by_role 関数だけをテストすればよくなります。
def filter_users_by_role(users, role):
return [user for user in users if role in user["roles"]]
def handler(event, context):
# admin ロールを保持しているユーザーだけを返す
users = filter_users_by_role(USERS, "admin")
return {"statusCode": 200, "body": users}
テストコードを作成
tests/test_app.py としてテストコードを書きます。
from src.app import filter_users_by_role
def test_filter_users_by_role():
USERS = [
{"username": "foo", "roles": []},
{"username": "bar", "roles": ["admin"]},
{"username": "baz", "roles": ["audit"]},
{"username": "qux", "roles": ["admin", "audit"]},
]
filtered_users = filter_users_by_role(USERS, "admin")
assert len(filtered_users) == 2
assert filtered_users[0]["username"] == "bar"
assert filtered_users[1]["username"] == "qux"
テストを実行
次のようにテストを実行します。仮想環境が有効になっていることに注意してください。
python -m pytest tests/
==================================================== test session starts ====================================================
platform darwin -- Python 3.13.0, pytest-8.3.4, pluggy-1.5.0
rootdir: /Users/konoken/cdk-serverless-articles/packages/02-first-unit-test/api/python
collected 1 item
tests/test_app.py . [100%]
===================================================== 1 passed in 0.00s =====================================================
CDK を含めた全体のファイル構成
テストが成功し、ビジネスロジックが正しいことが確認できました ! これでロジックを修正しても再実行が簡単になりますね。
CDK を含めた全体のファイル構成は次のようになります。CDK ではアプリケーションコードも一緒に管理することが一般的です。また、CDK のコードと Lambda 関数のコードが異なる言語で書かれていても問題ありません。Lambda のデプロイパッケージを作成するコマンドや除外するファイルなどは細かくカスタマイズできます。詳細は Blackbelt Online Seminar - CDK #3 を参照してください。
./
├── backend/
│ ├── .venv/
│ ├── requirements.txt
│ ├── src/
│ │ ├── init.py
│ │ ├── app.py # Lambda 関数のコード
│ │ └── main.py # ローカル実行用のスクリプト
│ └── tests/
│ └── test_app.py # テストコード
├── bin/
│ └── cdk.ts # CDK のコード
├── cdk.json
├── package.json
└── tsconfig.json
exclude を追加
Lambda のデプロイパッケージに開発用のファイルが含まれないように、exclude を追加することをおすすめします。
new Function(this, "ListUsersFunction", {
runtime: Runtime.PYTHON_3_13,
handler: "src/app.handler",
code: Code.fromAsset("backend", {
exclude: [".venv", "__pycache__", ".pytest_cache", "src/main.py", "tests"],
}),
});
「何をテストしようとしているか」を意識しよう
次回予告
今回は純粋な Python コードでしたが、実際の Lambda 関数では Amazon DynamoDB からユーザーを取得したり、Amazon S3 からファイルを読み取ったりと AWS サービスと連携することがほとんどです。そんなとき、どうやってテストをすればよいでしょうか ?
おや、次の「サーバーレス開発の達人」が来てくれたようです。
??? 「外部のサービスと連携したコードでも、すばやくテストする方法があるぞ !」
次回もお楽しみに !
参考コンテンツ集
筆者プロフィール
工藤 朋哉 (左側 / Kudo, Tomoya)
アマゾン ウェブ サービス ジャパン合同会社
Prototyping Engineer
技術的な課題を抱えている案件のプロトタイプを作成することで、お客様のプロジェクトを加速させるお手伝いをしています。プロトタイプ開発では主に AWS CDK を使ってお客様の環境でスムーズにデプロイが行えるように実装します。
高野 賢司 (右側 / Kono, Kenji / @konokenj)
アマゾン ウェブ サービス ジャパン合同会社
シニア ソリューション アーキテクト
名古屋在住のソリューションアーキテクトとして、主に東海地方の製造業のお客様を技術面でサポートしています。 Infrastructure as Code (IaC) のスペシャリストとして、イベント登壇や Baseline Environment on AWS (BLEA) の開発も行っています。

Did you find what you were looking for today?
Let us know so we can improve the quality of the content on our pages