Skip to content

Commit 5643fc4

Browse files
committed
Add tests for utils
1 parent 3607dbf commit 5643fc4

File tree

4 files changed

+113
-1
lines changed

4 files changed

+113
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
**/__pycache__/
2+
.vscode/
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
fastapi[standard]
22
psycopg[binary]
3-
boto3
3+
boto3
4+
pytest
5+
pytest-asyncio
6+
moto[s3]

services/question-service/tests/__init__.py

Whitespace-only changes.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import os
2+
import pytest
3+
import boto3
4+
from moto import mock_aws
5+
from app.utils import upload_to_s3, get_from_s3, delete_from_s3
6+
7+
@pytest.fixture(scope="function")
8+
def aws_credentials():
9+
"""Mocked AWS Credentials for moto."""
10+
os.environ["AWS_ACCESS_KEY_ID"] = "testing"
11+
os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
12+
os.environ["AWS_SECURITY_TOKEN"] = "testing"
13+
os.environ["AWS_SESSION_TOKEN"] = "testing"
14+
os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
15+
os.environ["S3_BUCKET_NAME"] = "test-bucket"
16+
17+
@pytest.fixture(scope="function")
18+
def mocked_aws(aws_credentials):
19+
"""
20+
Mock all AWS interactions
21+
Requires self creation of boto3 clients
22+
"""
23+
with mock_aws():
24+
yield
25+
26+
@pytest.fixture
27+
def mock_image_png():
28+
"""Fixture for a 1x1 black pixel PNG."""
29+
return b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0cIDATx\x9cc`\x00\x01\x00\x00\x05\x00\x01\xa2\x99V\xdd\x00\x00\x00\x00IEND\xaeB`\x82'
30+
31+
@pytest.fixture
32+
def mock_png_s3_keys():
33+
return "questions/qid1/0.png"
34+
35+
@pytest.fixture
36+
def mock_image_jpeg():
37+
"""Fixture for a 1x1 black pixel JPEG."""
38+
jpeg_data = b''.join([
39+
b'\xff\xd8', # SOI
40+
b'\xff\xe0\x00\x10', # APP0 segment (JFIF)
41+
b'JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00',
42+
b'\xff\xdb\x00C', b'\x00' * 67, # DQT
43+
b'\xff\xc0\x00\x11', # SOF0 (baseline DCT)
44+
b'\x08\x00\x01\x00\x01\x01\x01\x11\x00',
45+
b'\xff\xc4\x00\x14', b'\x00' * 20, # DHT
46+
b'\xff\xda\x00\x0c', # SOS
47+
b'\x01\x01\x00\x00?\x00',
48+
b'\x00\x00', # dummy compressed data
49+
b'\xff\xd9' # EOI
50+
])
51+
return jpeg_data
52+
53+
@pytest.fixture
54+
def mock_jpeg_s3_keys():
55+
return "questions/qid2/0.jpeg"
56+
57+
@mock_aws
58+
def test_upload_to_s3_empty_list():
59+
"""Tests that upload_to_s3 handles an empty list without error."""
60+
try:
61+
upload_to_s3([])
62+
except Exception as e:
63+
pytest.fail(f"upload_to_s3 raised an exception with an empty list: {e}")
64+
65+
@mock_aws
66+
def test_get_from_s3_empty_list():
67+
"""Tests that get_from_s3 handles an empty list correctly."""
68+
result = get_from_s3([])
69+
assert result == []
70+
71+
@mock_aws
72+
def test_delete_from_s3_empty_list():
73+
"""Tests that delete_from_s3 handles an empty list without error."""
74+
try:
75+
delete_from_s3([])
76+
except Exception as e:
77+
pytest.fail(f"delete_from_s3 raised an exception with an empty list: {e}")
78+
79+
@mock_aws
80+
def test_s3_upload_get_delete_integration(mocked_aws, mock_image_png, mock_png_s3_keys, mock_image_jpeg, mock_jpeg_s3_keys):
81+
"""
82+
Tests the full upload -> get -> delete cycle with image bytes using fixtures.
83+
"""
84+
s3_client = boto3.client("s3")
85+
s3_client.create_bucket(Bucket=os.getenv("S3_BUCKET_NAME"))
86+
87+
# 1. Upload
88+
files_to_upload = [
89+
(mock_image_png, mock_png_s3_keys),
90+
(mock_image_jpeg, mock_jpeg_s3_keys)
91+
]
92+
upload_to_s3(files_to_upload)
93+
94+
# 2. Get and Verify
95+
retrieved_data = get_from_s3([mock_png_s3_keys, mock_jpeg_s3_keys])
96+
assert len(retrieved_data) == 2
97+
assert retrieved_data[0] == mock_image_png
98+
assert retrieved_data[1] == mock_image_jpeg
99+
100+
# 3. Delete
101+
delete_from_s3([mock_png_s3_keys, mock_jpeg_s3_keys])
102+
103+
# 4. Verify Deletion
104+
# Check that getting the objects now raises an error
105+
with pytest.raises(s3_client.exceptions.NoSuchKey):
106+
s3_client.get_object(Bucket=os.getenv("S3_BUCKET_NAME"), Key=mock_png_s3_keys)
107+
with pytest.raises(s3_client.exceptions.NoSuchKey):
108+
s3_client.get_object(Bucket=os.getenv("S3_BUCKET_NAME"), Key=mock_jpeg_s3_keys)

0 commit comments

Comments
 (0)