Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions python-test-samples/apigw-lambda-dynamodb/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![python: 3.9](https://img.shields.io/badge/Python-3.9-green)](https://img.shields.io/badge/Python-3.9-green)
[![python: 3.13](https://img.shields.io/badge/Python-3.13-green)](https://img.shields.io/badge/Python-3.13-green)
[![AWS: DynamoDB](https://img.shields.io/badge/AWS-DynamoDB-blueviolet)](https://img.shields.io/badge/AWS-DynamoDB-blueviolet)
[![test: unit](https://img.shields.io/badge/Test-Unit-blue)](https://img.shields.io/badge/Test-Unit-blue)
[![test: integration](https://img.shields.io/badge/Test-Integration-yellow)](https://img.shields.io/badge/Test-Integration-yellow)
Expand Down Expand Up @@ -86,11 +86,15 @@ The [unit test tear-down](tests/unit/mock_test.py#L61-66) removes the mocked Dyn
To run the unit test, execute the following
```shell
# Run from the project directory serverless-test-samples/python-test-samples/apigw-lambda-dynamodb
# Verify Python version (Should show Python 3.13.x)

python3 --version
pip3 --version

# Create and Activate a Python Virtual Environment
# One-time setup

pip3 install virtualenv
python3 -m venv venv
python3 -m virtualenv venv
source ./venv/bin/activate

# install dependencies
Expand Down
2 changes: 1 addition & 1 deletion python-test-samples/apigw-lambda-dynamodb/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Resources:
TableName: !Ref DynamoDBTable
CodeUri: src/
Handler: app.lambda_handler
Runtime: python3.9
Runtime: python3.13
Architectures:
- x86_64
Environment:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def setUp(self) -> None:
"""
stack_name = TestApiGateway.get_stack_name()

client = boto3.client("cloudformation")
client = boto3.client("cloudformation", region_name=self.aws_region)

try:
response = client.describe_stacks(StackName=stack_name)
Expand All @@ -63,41 +63,64 @@ def setUp(self) -> None:
# Using unique id's per unit test will isolate test data
self.id_postfix = "_" + str(uuid4())


# Seed the DynamoDB Table with Test Data
dynamodb_resource = boto3.resource("dynamodb", region_name = self.aws_region)
dynamodb_table = dynamodb_resource.Table(name=self.dynamodb_table_name)
dynamodb_table.put_item(Item={"PK": "TEST001" + self.id_postfix,
"SK": "NAME#",
"data": "Unit Test Name Data"})

try:
dynamodb_resource = boto3.resource("dynamodb", region_name=self.aws_region)
dynamodb_table = dynamodb_resource.Table(name=self.dynamodb_table_name)
dynamodb_table.put_item(Item={"PK": "TEST001" + self.id_postfix,
"SK": "NAME#",
"data": "Unit Test Name Data"})
print(f"Successfully seeded test data for TEST001{self.id_postfix}")
except Exception as e:
print(f"Warning: Could not seed test data: {e}")
raise

def tearDown(self) -> None:
"""
# For tear-down, remove any data injected for the tests
# Take particular care to ensure these values are unique and identifiable as TEST data.
For tear-down, remove any data injected for the tests
Take particular care to ensure these values are unique and identifiable as TEST data.
"""
dynamodb_resource = boto3.resource("dynamodb", region_name = self.aws_region)
dynamodb_table = dynamodb_resource.Table(name=self.dynamodb_table_name)

for id in ["TEST001" + self.id_postfix,"TEST002" + self.id_postfix]:
id_items = dynamodb_table.query(
KeyConditionExpression=Key('PK').eq(id)
)
if "Items" in id_items:
for item in id_items["Items"]:
dynamodb_table.delete_item(Key={"PK":item["PK"],"SK":item["SK"]})
try:
dynamodb_resource = boto3.resource("dynamodb", region_name=self.aws_region)
dynamodb_table = dynamodb_resource.Table(name=self.dynamodb_table_name)

for id in ["TEST001" + self.id_postfix,"TEST002" + self.id_postfix]:
try:
id_items = dynamodb_table.query(
KeyConditionExpression=Key('PK').eq(id)
)
if "Items" in id_items:
for item in id_items["Items"]:
dynamodb_table.delete_item(Key={"PK":item["PK"],"SK":item["SK"]})
print(f"Successfully cleaned up test data for {id}")
except Exception as item_error:
print(f"Could not clean up items for {id}: {item_error}")
except Exception as e:
print(f"Warning: tearDown cleanup failed (this may be a credentials issue): {e}")
print("Test data may remain in DynamoDB - clean up manually if needed")

def test_api_gateway_200(self):
"""
Call the API Gateway endpoint and check the response for a 200
"""
response = requests.get(self.api_endpoint.replace("{id}","TEST001" + self.id_postfix))
self.assertEqual(response.status_code, requests.codes.ok)
try:
response = requests.get(self.api_endpoint.replace("{id}","TEST001" + self.id_postfix))
print(f"API Response Status: {response.status_code}")
print(f"API Response Body: {response.text}")
self.assertEqual(response.status_code, requests.codes.ok)
except Exception as e:
print(f"Test failed with error: {e}")
raise

def test_api_gateway_404(self):
"""
Call the API Gateway endpoint and check the response for a 404 (id not found)
"""
response = requests.get(self.api_endpoint.replace("{id}","TEST002" + self.id_postfix))
self.assertEqual(response.status_code, requests.codes.not_found)
try:
response = requests.get(self.api_endpoint.replace("{id}","TEST002" + self.id_postfix))
print(f"API Response Status: {response.status_code}")
print(f"API Response Body: {response.text}")
self.assertEqual(response.status_code, requests.codes.not_found)
except Exception as e:
print(f"Test failed with error: {e}")
raise
11 changes: 6 additions & 5 deletions python-test-samples/apigw-lambda-dynamodb/tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pytest
pytest>=7.0.0
pytest-mock
boto3
moto
aws_lambda_powertools
moto>=4.0.0
boto3>=1.26.0
aws-lambda-powertools>=2.0.0
aws-xray-sdk
fastjsonschema
pyyaml
requests>=2.28.0
pyyaml>=6.0
uuid
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
import yaml
import boto3
from boto3.dynamodb.conditions import Key
import moto
from moto import mock_aws # Changed from import moto


# Import the handler under test
from src import app

# Mock the DynamoDB Service during the test
@moto.mock_dynamodb

@mock_aws # Changed from @moto.mock_dynamodb
class TestSampleLambdaWithDynamoDB(TestCase):
"""
Unit Test class for src/app.py
Expand Down Expand Up @@ -136,7 +135,4 @@ def test_lambda_handler_notfound_path(self):
# Check the log entry item
for item in id_items["Items"]:
self.assertEqual(item["data"], "NOTFOUND: Name Not Found for ID TEST002" + self.id_postfix)
self.assertEqual(item["SK"][0:11], "DT#" + datetime.now().strftime("%Y%m%d"))



self.assertEqual(item["SK"][0:11], "DT#" + datetime.now().strftime("%Y%m%d"))