Lorsque vous travaillez avec des technologies cloud, vous vous retrouvez souvent confrontés à un dilemme lors de la mise en place de tests. Comment pouvez-vous interagir avec des services distants sans déployer un environnement complet qui pourrait alourdir vos coûts ? La réponse traditionnelle serait d’utiliser des mocks, mais avec plus de 200 services proposés par AWS, ne serait-il pas plus judicieux d’utiliser une bibliothèque qui effectue déjà le travail pour vous ? C’est là qu’intervient Moto
Moto est une bibliothèque qui simplifie grandement la création de mocks pour vos tests basés sur l’infrastructure AWS.
Dans cet article, nous allons explorer comment mettre en place des tests pour vos fonctions AWS Lambdas en utilisant Pytest et Moto.
Prérequis
Pour commencer, nous devons installer deux bibliothèques essentielles : Pytest et Moto. Vous pouvez le faire en utilisant pip :
pip install pytest
pip install moto
Pour la suite de cet article, nous supposerons que vous avez un dossier nommé tests à la racine de votre projet.
Mise en place des fixtures
Une fois les bibliothèques installées et le dossier tests créé, nous allons maintenant écrire nos premières fixtures. Si vous n’êtes pas familier avec le concept de fixtures, je vous invite à consulter la documentation.
Tout d’abord, pour éviter toute interaction accidentelle avec un environnement AWS distant, il est crucial de surcharger les variables d’environnement liées à AWS. Pour ce faire, nous allons mettre en place une configuration globale exécutée avant et après chaque test, grâce à Pytest.
# conftest.py
import pytest
monkey_patch = pytest.MonkeyPatch()
def pytest_runtest_setup():
"""Remplace les variables d'environnement liées à AWS pour éviter les appels aux services AWS pendant les tests"""
monkey_patch.setenv('AWS_ACCESS_KEY_ID', 'testing')
monkey_patch.setenv('AWS_SECRET_ACCESS_KEY', 'testing')
monkey_patch.setenv('AWS_SECURITY_TOKEN', 'testing')
monkey_patch.setenv('AWS_SESSION_TOKEN', 'testing')
monkey_patch.setenv('AWS_DEFAULT_REGION', 'eu-west-1')
monkey_patch.setenv('AWS_REGION', 'eu-west-1')
def pytest_runtest_teardown():
"""Restaure les variables d'environnement AWS d'origine après les tests"""
monkey_patch.delenv('AWS_ACCESS_KEY_ID')
monkey_patch.delenv('AWS_SECRET_ACCESS_KEY')
monkey_patch.delenv('AWS_SECURITY_TOKEN')
monkey_patch.delenv('AWS_SESSION_TOKEN')
monkey_patch.delenv('AWS_DEFAULT_REGION')
monkey_patch.delenv('AWS_REGION')
Maintenant que nous sommes sûrs qu’aucune requête ne sera transmise à AWS, nous pouvons passer à la définition des mocks pour les services AWS à l’aide de fixtures. Voici un exemple de fixtures pour Amazon S3 et DynamoDB qui renverront des mocks de ces services respectifs.
# conftest.py
import boto3
import pytest
from moto import mock_s3
@pytest.fixture()
def s3_client():
"""Mock s3 client"""
with mock_s3():
yield boto3.client("s3")
@pytest.fixture()
def dynamodb_client():
"""Mock DynamoDB client"""
with mock_dynamodb():
yield boto3.client("dynamodb")
Écriture des tests
Maintenant que nous avons mis en place nos fixtures pour Amazon S3 et DynamoDB, nous pouvons écrire nos tests. Expliquons comment utiliser ces fixtures pour écrire des tests efficaces pour vos fonctions Lambdas. Voici un exemple simple de test pour une fonction Lambda qui interagit avec Amazon DynamoDB en utilisant la fixture dynamodb_client
:
# test_lambda.py
from importlib import import_module
from dataclasses import dataclass
import pytest
@pytest.fixture()
def my_lambda():
yield import_module("my_lambda")
@pytest.fixture()
def lambda_context():
@dataclass
class LambdaContext:
function_name: str = "test"
memory_limit_in_mb: int = 128
invoked_function_arn: str = (
"arn:aws:lambda:eu-west-1:123456789012:function:test"
)
aws_request_id: str = "da658bd3-2d6f-4e7b-8ec2-937234644fdc"
return LambdaContext()
def test_lambda_with_dynamodb_interaction(dynamodb_client, my_lambda, lambda_context):
# Code de test pour une fonction Lambda qui interagit avec DynamoDB
dynamodb_client.create_table(
TableName='my_table',
KeySchema=[{'AttributeName': 'id', 'KeyType': 'HASH'}],
AttributeDefinitions=[{'AttributeName': 'id', 'AttributeType': 'N'}],
ProvisionedThroughput={'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5}
)
# Exécutez votre fonction Lambda ici
event = {}
my_lambda.handler(event, lambda_context)
# Assurez-vous de vérifier les résultats attendus de votre fonction Lambda
assert True # Remplacez ceci par votre propre assertion
De manière similaire, vous pouvez écrire des tests pour vos fonctions Lambdas qui interagissent avec S3 en utilisant la fixture s3_client
.
En conclusion
En utilisant Pytest et Moto, vous pouvez simplifier considérablement le processus de test de vos fonctions AWS Lambdas. Les fixtures que nous avons mises en place vous permettent de simuler les interactions avec les services AWS sans avoir besoin de dépenser des ressources réelles. Cela vous aide à développer et à déboguer vos fonctions Lambdas plus rapidement et de manière plus fiable.
Avec cette approche, vous pouvez avoir confiance dans le comportement de vos fonctions Lambda sans craindre de coûts inattendus liés aux tests dans votre environnement AWS réel.