Skip to content

Commit 7ee6397

Browse files
committed
test: implement comprehensive unit and integration test suite
1 parent bf33341 commit 7ee6397

5 files changed

Lines changed: 132 additions & 0 deletions

File tree

tests/e2e/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# E2E tests

tests/integration/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Integration tests
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import boto3
2+
import pytest
3+
import os
4+
5+
# Use LocalStack endpoint if running in Docker/LocalStack env
6+
ENDPOINT_URL = os.environ.get("LOCALSTACK_ENDPOINT", "http://localhost:4566")
7+
8+
@pytest.fixture
9+
def s3_client():
10+
return boto3.client("s3", endpoint_url=ENDPOINT_URL, region_name="us-east-1")
11+
12+
@pytest.fixture
13+
def dynamodb_client():
14+
return boto3.client("dynamodb", endpoint_url=ENDPOINT_URL, region_name="us-east-1")
15+
16+
@pytest.fixture
17+
def iam_client():
18+
return boto3.client("iam", endpoint_url=ENDPOINT_URL, region_name="us-east-1")
19+
20+
def test_s3_bucket_exists(s3_client):
21+
# This assumes the bucket name from our terraform/main.tf default
22+
bucket_name = "portfolio-cloud-dev-dev-portfolio-uploads"
23+
try:
24+
response = s3_client.head_bucket(Bucket=bucket_name)
25+
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
26+
except Exception as e:
27+
pytest.fail(f"Bucket {bucket_name} does not exist or is not accessible: {e}")
28+
29+
def test_dynamodb_table_exists(dynamodb_client):
30+
table_name = "portfolio-cloud-dev-dev-metadata"
31+
try:
32+
response = dynamodb_client.describe_table(TableName=table_name)
33+
assert response["Table"]["TableStatus"] == "ACTIVE"
34+
except Exception as e:
35+
pytest.fail(f"Table {table_name} does not exist: {e}")
36+
37+
def test_iam_roles_exist(iam_client):
38+
roles = ["upload_lambda_role", "metadata_lambda_role"]
39+
for role_name in roles:
40+
try:
41+
response = iam_client.get_role(RoleName=role_name)
42+
assert response["Role"]["RoleName"] == role_name
43+
except Exception as e:
44+
pytest.fail(f"IAM Role {role_name} does not exist: {e}")

tests/unit/test_sample.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import boto3
2+
import pytest
3+
from moto import mock_s3
4+
5+
@mock_s3
6+
def test_s3_bucket_creation():
7+
s3 = boto3.client("s3", region_name="us-east-1")
8+
bucket_name = "test-bucket"
9+
s3.create_bucket(Bucket=bucket_name)
10+
11+
response = s3.list_buckets()
12+
buckets = [bucket["Name"] for bucket in response["Buckets"]]
13+
assert bucket_name in buckets

tests/unit/test_upload_lambda.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import json
2+
import base64
3+
import pytest
4+
import boto3
5+
from moto import mock_s3, mock_dynamodb
6+
from src.lambda.upload.handler import handler
7+
8+
@pytest.fixture
9+
def aws_credentials():
10+
"""Mocked AWS Credentials for moto."""
11+
import os
12+
os.environ["AWS_ACCESS_KEY_ID"] = "testing"
13+
os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
14+
os.environ["AWS_SECURITY_TOKEN"] = "testing"
15+
os.environ["AWS_SESSION_TOKEN"] = "testing"
16+
os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
17+
os.environ["BUCKET_NAME"] = "test-bucket"
18+
os.environ["DYNAMODB_TABLE"] = "test-table"
19+
20+
@mock_s3
21+
@mock_dynamodb
22+
def test_upload_handler_success(aws_credentials):
23+
# Setup mock S3
24+
s3 = boto3.client("s3", region_name="us-east-1")
25+
s3.create_bucket(Bucket="test-bucket")
26+
27+
# Setup mock DynamoDB
28+
db = boto3.resource("dynamodb", region_name="us-east-1")
29+
db.create_table(
30+
TableName="test-table",
31+
KeySchema=[
32+
{"AttributeName": "project_id", "KeyType": "HASH"},
33+
{"AttributeName": "timestamp", "KeyType": "RANGE"}
34+
],
35+
AttributeDefinitions=[
36+
{"AttributeName": "project_id", "AttributeType": "S"},
37+
{"AttributeName": "timestamp", "AttributeType": "N"}
38+
],
39+
ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}
40+
)
41+
42+
# Mock event
43+
file_content = b"hello world"
44+
encoded_content = base64.b64encode(file_content).decode("utf-8")
45+
event = {
46+
"body": encoded_content,
47+
"isBase64Encoded": True,
48+
"headers": {
49+
"file-name": "test.txt",
50+
"Content-Type": "text/plain",
51+
"project-id": "proj-123"
52+
}
53+
}
54+
55+
# Call handler
56+
response = handler(event, None)
57+
58+
# Verify response
59+
assert response["statusCode"] == 200
60+
body = json.loads(response["body"])
61+
assert body["message"] == "Upload e registro concluídos"
62+
63+
# Verify S3 content
64+
obj = s3.get_object(Bucket="test-bucket", Key="uploads/proj-123/test.txt")
65+
assert obj["Body"].read() == file_content
66+
67+
# Verify DynamoDB metadata
68+
table = db.Table("test-table")
69+
items = table.scan()["Items"]
70+
assert len(items) == 1
71+
assert items[0]["project_id"] == "proj-123"
72+
assert items[0]["filename"] == "test.txt"
73+
assert items[0]["status"] == "UPLOADED"

0 commit comments

Comments
 (0)