みなさん、こんにちは!AWS Lambdaを使っている方、テストの仕方で悩んだことありませんか?Lambdaはイベント駆動型のサーバーレスコンピューティングサービスで、いろいろな使い方ができるんですが、実際にそのLambda関数がうまく動作しているかどうか、手動で確認するのは結構面倒ですよね。そこで今回は、Pythonのテストフレームワークであるpytest
と、AWSサービスをモックしてくれる便利なライブラリmoto
を使ってLambdaを呼び出す方法を紹介します!
テストを書くのはちょっと…という方も、心配しないでください。テストを書くことで、コードの品質が向上し、変更を加えた際の不具合をすぐに見つけられるようになるんです。少しずつ、コツを掴んでいきましょう!
それでは、早速やってみましょう!
Lambda関数を作成しよう
まずは、AWS Lambdaの簡単な関数を作成しましょう。今回は、2つの数値を受け取って、その合計を返すLambda関数を作成します。コードは以下のようになります。
import json def lambda_handler(event, context): num1 = event.get("num1") num2 = event.get("num2") if num1 is None or num2 is None: return { "statusCode": 400, "body": json.dumps({"error": "num1またはnum2が指定されていません"}) } result = num1 + num2 return { "statusCode": 200, "body": json.dumps({"result": result}) }
このLambda関数は、event
オブジェクトにnum1
とnum2
というキーが含まれているかを確認し、含まれていればその合計を返します。もしどちらかが欠けている場合は、エラーメッセージを返す仕組みになっています。
pytestでテストを作成する
次に、このLambda関数が正しく動作するかどうかを、pytestでテストしてみます。まず、pytestの基本的な構造を確認しましょう。テストファイルは、test_lambda.py
という名前で作成します。
import json import pytest from my_lambda_function import lambda_handler # 自作のLambda関数をインポート def test_lambda_invoke_success(): # 正常な入力をシミュレート event = {"num1": 5, "num2": 10} result = lambda_handler(event, None) # 期待される結果 expected_body = {"result": 15} assert result["statusCode"] == 200 assert json.loads(result["body"]) == expected_body def test_lambda_invoke_missing_params(): # num2が欠けているシミュレーション event = {"num1": 5} result = lambda_handler(event, None) # エラーメッセージの期待値 expected_body = {"error": "num1またはnum2が指定されていません"} assert result["statusCode"] == 400 assert json.loads(result["body"]) == expected_body
ここで2つのテストを作成しました。1つ目のテストでは、num1
とnum2
が正しく与えられた場合の結果をチェックしています。2つ目のテストでは、num2
が欠けている場合にエラーメッセージが返されるかを確認しています。
motoでAWS Lambdaをモックする
では、次にmoto
を使って、Lambdaの呼び出しをモックしてみましょう。moto
はAWSのサービスを模倣するため、実際にAWS環境を用意しなくてもテストができる便利なライブラリです。
まず、moto
をインストールします。
pip install moto
moto
を使ってLambdaをモックする場合、Lambdaの呼び出しをAWSに送らず、代わりにモックされた環境でテストを行うことができます。これにより、コストをかけずにローカルでテストできるようになります。
では、次に実際のテストコードにmoto
を組み込んでみましょう。
import json import boto3 import pytest from moto import mock_lambda # Lambda関数をデプロイするモックを作成 @pytest.fixture def lambda_client(): with mock_lambda(): client = boto3.client("lambda", region_name="us-east-1") # Lambda関数を作成 client.create_function( FunctionName="MyLambdaFunction", Runtime="python3.8", Role="arn:aws:iam::123456789012:role/execution_role", Handler="my_lambda_function.lambda_handler", Code={ 'ZipFile': b"placeholder code", # 簡易的にZipFileを指定 }, Description="This is a test lambda function", Timeout=3, MemorySize=128 ) yield client # Lambda関数をモックでテスト def test_invoke_lambda(lambda_client): # 正常なリクエストをシミュレーション payload = json.dumps({"num1": 3, "num2": 7}) response = lambda_client.invoke( FunctionName="MyLambdaFunction", Payload=payload ) response_payload = json.loads(response['Payload'].read()) # 期待される結果 expected_result = {"result": 10} assert response_payload["statusCode"] == 200 assert json.loads(response_payload["body"]) == expected_result
このコードでは、まずmoto
を使ってAWS Lambdaのモック環境を作成し、その中でLambda関数をデプロイします。その後、invoke
メソッドを使ってLambda関数を呼び出し、結果をテストしています。
テスト結果
ここまでのコードを実行すると、Lambdaが正しくモックされ、期待通りの動作をするかどうかを確認できます。
$ pytest test_lambda.py
実行結果は以下のようになります。
============================= test session starts ============================== collected 2 items test_lambda.py .. [100%] ============================== 2 passed in 0.45s ===============================
この結果からもわかる通り、無事に2つのテストが成功しました!
まとめ
今回は、pytest
とmoto
を使ってAWS Lambdaのテストを行う方法を学びました。Lambdaをローカル環境でテストするためには、実際にAWS環境を用意しなくても、moto
を使ってモックを作成することができるので、とても便利です。特に、開発初期や費用を抑えたいときには、この方法でどんどんテストを追加していくのがおすすめです。
これで、Lambda関数のテストに自信を持って取り組めるようになったと思います。次回は、もう少し進んで、他のAWSサービスとの連携についても触れていきたいと思います。ぜひ次回の記事も楽しみにしていてくださいね!
もし、この記事が役に立ったと思っていただけたら、ぜひツイッターでフォローしてください!お互いに学び合いながら、もっと成長していきましょう。それでは、また次回お会いしましょう!