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

Yunhao Jiao
サーバーレス関数のテスト方法: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関数には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

サーバーレステストのパイプライン:

  1. ユニットテスト — 高速、全コミット時に実行
  2. ハンドラーのインテグレーションテスト — 全PRに対し、モックされたイベントオブジェクトを使用して実行
  3. プレビューデプロイメントに対するE2Eテスト — Vercel/Netlifyのプレビューが作成されると、TestSpriteが自動的に実行
  4. 本番スモークテスト — 本番関数に対するスケジュール実行

サーバーレス関数テストをパイプラインに追加する →