サーバーレス関数のテスト方法:AWS Lambda、Vercel Functions、Edge Runtime

サーバーレス関数は、モダンなWeb開発におけるバックエンドコードの主要なパターンの一つとなっています。AWS Lambda、Vercelサーバーレス関数、Netlify Functions、Cloudflare Workers、Next.jsのルートハンドラーはいずれもサーバーレス環境であり、テスト方法に影響を与える固有の特性を持っています。
テストにおける核心的な課題:サーバーレス関数はエフェメラルなクラウド管理環境で実行されるため、ローカルでの再現が難しく、コールドスタート、メモリ制限、実行タイムアウト、ステートレスな実行といった独自の制約があります。
サーバーレステストが異なる理由
ステートレス性
サーバーレス関数は設計上ステートレスです。各呼び出しはゼロから開始され、呼び出し間でインメモリのステートは保持されません。これはスケーラビリティの観点では優れていますが、呼び出し間で蓄積されたステートに依存するテストは、永続的なプロセスを持つローカル環境では通過しても、本番環境では失敗することを意味します。
コールドスタート
最近呼び出されていない関数は「コールド」状態となり、起動に時間がかかります。レスポンスタイムを前提とするテストは、テスト時に関数がウォーム状態だったかコールド状態だったかによって、結果が不安定になることがあります。
環境の違い
ローカル実行環境(直接実行するNode.js、WorkersのWrangler devなど)はクラウド環境を完全に再現できません。ランタイムのバージョン、環境変数の扱い、利用可能なAPI、メモリ制限が異なる場合があります。ローカルで通過したテストが、環境的な理由から本番環境で失敗することがあります。
ベンダー固有のAPI
各サーバーレスプラットフォームにはベンダー固有のAPIがあります:AWS Lambdaにはeventオブジェクトとcontextオブジェクトがあり、Vercel FunctionsにはreqとRes(または新しいRequest/Responseパターン)があり、Cloudflare Workersにはfetchハンドラーがあります。テストでは、これらのプラットフォーム固有の入力を正しくモックする必要があります。
サーバーレスアプリケーションのテスト層
関数ロジックのユニットテスト
サーバーレス関数のロジックのほとんどは、サーバーレスランタイムから独立してテストされる純粋な関数として切り出すことができます:
calculateShippingのユニットテストは、サーバーレス環境をシミュレートすることなく、すべてのビジネスロジックをカバーします。ハンドラー自体はインテグレーションレベルでテストされます。
ハンドラーのインテグレーションテスト
モックした入力でハンドラーを直接呼び出してテストします:
AWS Lambdaのテスト
Lambda関数については、lambda-localパッケージまたはモックされたイベントオブジェクトを使ったハンドラーの直接呼び出しを利用します:
デプロイ済み関数に対するE2Eテスト
最もリアルなテストは、実際の環境でサーバーレス関数を呼び出すことです。TestSpriteのエージェンティックテストは、プレビューデプロイメント(Vercel、Netlify、Render、Fly.io)に対してE2Eテストを実行し、実際のHTTPインターフェースと実際のリクエスト/レスポンスサイクルを通じてサーバーレス関数を検証します。
これにより、ローカルテストでは検出できない種類の障害を捕捉できます:環境変数の差異、ランタイムAPIの可用性、コールドスタートのタイムアウト問題、ベンダー固有の動作などです。
サーバーレス固有の懸念事項のテスト
冪等性
サーバーレス関数は、同一のイベントに対して複数回呼び出される場合があります(キュー、Webhook、イベントストリームのリトライロジックによる)。重複した呼び出しが重複した副作用を生じさせないことをテストしてください:
- 同じ決済イベントを2回処理しても、2回請求されないこと
- 同じWebhookイベントを2回処理しても、重複したレコードが作成されないこと
- 操作は設計上冪等であること(常に作成するのではなく、存在しない場合のみ作成する)
コールドスタートのパフォーマンス
レイテンシに敏感なサーバーレス関数については、実際のクラウド環境でコールドスタート時間をテストしてください。関数のコールドスタートが3秒かかり、SLAが500ms未満のレスポンスタイムを要求している場合は、ウォーミング戦略が必要になります。
環境変数のカバレッジ
関数が、欠損または不正な環境変数を適切に処理することをテストしてください。環境変数が欠損している場合、関数は誤った動作をサイレントに行うのではなく、明確なエラーでフェイルファストすべきです。
タイムアウトの動作
長時間実行される処理が、関数の実行タイムアウトを適切に処理することをテストしてください。Lambdaのタイムアウトが30秒でデータベースクエリが35秒かかる場合、関数は処理の途中で終了します。これによってデータが不整合な状態に残らないことを確認してください。
サーバーレステストのCI/CD
サーバーレスのテストパイプライン:
- ユニットテスト — 高速、すべてのコミットで実行
- ハンドラー統合テスト — PRごとに、モックされたイベントオブジェクトを使用して実行
- プレビューデプロイメントに対するE2Eテスト — Vercel/Netlifyのプレビューが作成されると、TestSpriteが自動的に実行
- 本番環境スモークテスト — 本番関数に対してスケジュール実行
サーバーレス関数テストをパイプラインに追加する →