2024年8月14日にリリースされた testcontainers-python v4.8.0 の新機能を確認していたら new: Added AWS Lambda module
と書いてあって,これは何だろう〜と気になって試してみた❗️
簡単に言えば,テスト実行時に testcontainers-python で AWS Lambda 関数(コンテナ)を起動して,AWS Lambda RIE (Runtime Interface Emulator) エンドポイント /2015-03-31/functions/function/invocations
を呼び出したレスポンスを assert できる機能だった💡AWS Lambda 関数(コンテナ)の振る舞いをデプロイする前にテストできる \( 'ω')/
さっそく AWSLambdaContainer を試す
ディレクトリ構成
. ├── Dockerfile ├── requirements-test.txt ├── src │ └── app.py └── tests └── test_app.py
👾 Dockerfile
まず Dockerfile
を作る.Python ベースイメージを使えば AWS Lambda RIC (Runtime Interface Clients) と AWS Lambda RIE (Runtime Interface Emulator) をセットアップしなくて OK👌 Ubuntu などをベースイメージにする場合は別途セットアップする必要がある.
FROM public.ecr.aws/lambda/python:3.12 COPY src/app.py ${LAMBDA_TASK_ROOT} CMD [ "app.handler" ]
👾 src/app.py
AWS Lambda 関数で実行するコードはサンプルとして受け取った event
をそのまま返す実装にした.
def handler(event, context): return event
👾 tests/test_app.py
以下のドキュメントを参考にしつつテストコードを書いてみた❗️
testcontainers-python.readthedocs.io
まず DockerImage
で Dockerfile
からコンテナイメージをビルドしつつ,AWSLambdaContainer
で AWS Lambda 関数(コンテナ)を起動する💡そして send_request()
で AWS Lambda RIE (Runtime Interface Emulator) のエンドポイント /2015-03-31/functions/function/invocations
を呼び出す.
今回は4種類の assert
を実装した👌
- エンドポイント
- ステータスコード
- レスポンス (
title
) - レスポンス (
url
)
import re from testcontainers.aws import AWSLambdaContainer from testcontainers.core.image import DockerImage def test_function(): with DockerImage(path='.') as image: with AWSLambdaContainer(image=image, port=8080) as func: pattern = r'http://localhost:\d+/2015-03-31/functions/function/invocations' assert re.match(pattern, func.get_api_url()) response = func.send_request( { 'title': 'kakakakakku blog', 'url': 'https://kakakakakku.hatenablog.com/', } ) body = response.json() assert response.status_code == 200 assert body['title'] == 'kakakakakku blog' assert body['url'] == 'https://kakakakakku.hatenablog.com/'
ちなみに get_api_url()
という関数はドキュメントには載ってなかったけど,実装を確認しているときに発見した.ポート部分は毎回変わるけど http://localhost:61522/2015-03-31/functions/function/invocations
という値が返ってくる😀 まさに RIE エンドポイント \( 'ω')/
👾 requirements-test.txt
AWSLambdaContainer
の依存する ServerContainer
は HTTP リクエストを操作するライブラリとして内部的に HTTPX を使っているようだった.
よって,AWSLambdaContainer
のレスポンスは HTTPX オブジェクトになるため,セットアップを忘れると ModuleNotFoundError: No module named 'httpx'
というエラーが出る.今回 requirements-test.txt
は以下のようにした.
httpx==0.27.0 pytest==8.3.2 testcontainers==4.8.0
✅ 動作確認
OK👌
$ python -m pytest --verbose tests/test_app.py::test_function PASSED [100%]
まとめ
testcontainers-python v4.8.0 の新機能「AWSLambdaContainer」を試してみた❗️
ちなみに個人的には AWS Lambda 関数を実装するときは handler()
と main()
を分割して,main()
をテストしている.ドキュメントにもベストプラクティス「Lambda ハンドラーをコアロジックから分離します」と紹介されていたりする📝
今回の AWSLambdaContainer
では AWS Lambda RIE (Runtime Interface Emulator) を使って AWS Lambda 関数(コンテナ)の振る舞いをテストできるため,あくまで個人的には単体テストとしてではなく統合テストとして活用できそうかなと思った.