🐍
pytest + MotoでS3, Secrets Managerのテストコードを書く
pytestとMotoでシンプルなテストコードを書いてみる。
pytestはもうすでにinstallしている前提です。
環境
- Python: 3.11.9
- moto: 5.0.6
- pytest: 8.2.0
Motoとは
単体テストでAWSサービスをモックしてくれるライブラリ。
デコレーターを付与するだけで、boto3などで使用しているAWSサービスへの呼び出しが自動でモック化されます。
motoはpytestでAWSのAPIが呼び出されると、実際のAWSではなくmotoによって提供されるモックのAPIにルーティングし、モック化してくれます。
そのためテスト上で、仮想的なAWSリソースを作成・操作・削除が可能です。
また操作は全てメモリ内で行われ、実際のAWSアカウントには影響を与えないようになっています。
Install Moto
まだMotoをインストールしていない場合は、以下のコマンドでインストールする。
all
にするとmotoで対応されているすべてのサービスがインストールされます。
対応されているサービス一覧
pip install 'moto[s3,secretsmanager]'
# or
pip install 'moto[all]'
S3とSecrets Managerを参照している関数をテストする
S3とSecrets Managerどちらもget系を記載。
S3
boto3のget_object
を使用している関数をテストしたい場合
テスト対象の関数
import boto3
def get_s3_object(bucket_name, key):
s3 = boto3.client('s3')
response = s3.get_object(Bucket=bucket_name, Key=key)
return response['Body'].read()
テストコード
import boto3
import pytest
from moto import mock_aws
@mock_aws
def test_s3_bucket_creation():
bucket_name = 'test-s3-bucket'
key = 'test-object'
body = b'dymmy contents for UT'
# テスト用にS3バケットとオブジェクトを作成する
s3 = boto3.client('s3')
s3.create_bucket(Bucket=bucket_name)
s3.put_object(Bucket=bucket_name, Key=key, Body=body)
# テスト対象の関数を呼び出す
retrieved_body = get_s3_object(bucket_name, key)
assert retrieved_body == body
Secrets Manager
boto3のget_secret_value
を使用している関数をテストしたい場合
テスト対象の関数
import boto3
def get_secret_value(secret_name):
client = boto3.client('secretsmanager', 'ap-north-east1')
response = client.get_secret_value(SecretId=secret_name)
return response['SecretString']
テストコード
import boto3
import pytest
from moto import mock_aws
@mock_aws
def test_get_secret_value():
secret_name = 'test-secret'
secret_value = 'my-secret-value'
# テスト用にダミーのシークレットを作成する
client = boto3.client('secretsmanager')
client.create_secret(Name=secret_name, SecretString=secret_value)
# テスト対象の関数を呼び出す
retrieved_secret_value = get_secret_value(secret_name)
assert retrieved_secret_value == secret_value
Fixtureを使用する
もしくはfixtureを使用して、s3のバケット作成やシークレット作成を事前にしておくのも良いです。
conftest.py
import boto3
import pytest
from moto import mock_secretsmanager
@pytest.fixture
def aws_resources():
with mock_secretsmanager():
client = boto3.client('secretsmanager')
client.create_secret(Name='test-secret', SecretString='my-secret-value')
yield client
テストコード
def test_get_secret_value(aws_resources):
client = aws_resources
retrieved_secret_value = get_secret_value('test-secret')
assert retrieved_secret_value == 'my-secret-value'
参考
公式ドキュメント
Discussion