Skip to content

Commit 64d8671

Browse files
committed
Translate basic django test to sqlalchemy
1 parent 799e9b0 commit 64d8671

4 files changed

Lines changed: 96 additions & 146 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,5 @@ filterwarnings = [
8585
]
8686

8787
[tool.poetry.plugins."sqlalchemy.dialects"]
88-
"postgresql.aws_wrapper" = "aws_advanced_python_wrapper.sqlalchemy.orm_dialect:SqlAlchemyOrmPgDialect"
88+
"postgresql.aws_wrapper_psycopg" = "aws_advanced_python_wrapper.sqlalchemy.pg_orm_dialect:SqlAlchemyOrmPgDialect"
89+
"mysql.aws_wrapper_mysqlconnector" = "aws_advanced_python_wrapper.sqlalchemy.mysql_orm_dialect:SqlAlchemyOrmMysqlDialect"

tests/integration/container/sqlalchemy/test_sqlalchemy_basic.py

Lines changed: 92 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
from typing import Any
2222

2323
import pytest
24-
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
25-
from sqlalchemy import Column, Integer, String, Boolean, DateTime
24+
from sqlalchemy.orm import declarative_base, sessionmaker
25+
from sqlalchemy import create_engine, Column, ForeignKey, Integer, BigInteger, SmallInteger, Float, Numeric, String, Boolean, Date, Time, DateTime, Text, JSON
2626

2727
from tests.integration.container.utils.rds_test_utility import RdsTestUtility
2828
from ..utils.conditions import (disable_on_features, enable_on_deployments,
@@ -39,173 +39,120 @@
3939
TestEnvironmentFeatures.BLUE_GREEN_DEPLOYMENT,
4040
TestEnvironmentFeatures.PERFORMANCE])
4141
class TestSqlAlchemy:
42-
TestModel: Any
43-
DataTypeModel: Any
44-
Author: Any
45-
Book: Any
46-
4742
@pytest.fixture(scope='class')
4843
def rds_utils(self):
4944
region: str = TestEnvironment.get_current().get_info().get_region()
5045
return RdsTestUtility(region)
5146

52-
@pytest.fixture(scope='class')
53-
def sqlalchemy_models(self, sqlalchemy_setup):
54-
"""Create SQLAlchemy models after SQLAlchemy is set up"""
55-
#Base = declarative_base()
56-
57-
class Base(DeclarativeBase):
58-
pass
47+
Base = declarative_base()
5948

6049
class TestModel(Base):
6150
"""Basic test model for SQLAlchemy ORM functionality"""
6251
__tablename__ = 'sqlalchemy_test_model'
6352

64-
name: Mapped[str] = mapped_column(String(100))
65-
email: Mapped[str] = mapped_column(String, primary_key=True)
66-
age: Mapped[int] = mapped_column(Integer)
67-
is_active: Mapped[bool] = mapped_column(Boolean)
68-
created_at: Mapped[datetime] = mapped_column(DateTime)
69-
70-
'''
71-
class DataTypeModel(models.Model):
72-
"""Model for testing various data types"""
73-
# String fields
74-
char_field = models.CharField(max_length=255, null=True, blank=True)
75-
text_field = models.TextField(null=True, blank=True)
76-
77-
# Numeric fields
78-
integer_field = models.IntegerField(null=True, blank=True)
79-
big_integer_field = models.BigIntegerField(null=True, blank=True)
80-
decimal_field = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
81-
float_field = models.FloatField(null=True, blank=True)
82-
83-
# Boolean field
84-
boolean_field = models.BooleanField(default=False)
85-
86-
# Date/Time fields
87-
date_field = models.DateField(null=True, blank=True)
88-
time_field = models.TimeField(null=True, blank=True)
89-
datetime_field = models.DateTimeField(null=True, blank=True)
90-
91-
# JSON field (MySQL 5.7+)
92-
json_field = models.JSONField(null=True, blank=True)
93-
94-
class Meta:
95-
app_label = 'test_app'
96-
db_table = 'django_data_type_model'
97-
98-
class Author(models.Model):
99-
"""Author model for relationship testing"""
100-
name = models.CharField(max_length=100)
101-
email = models.EmailField()
102-
birth_date = models.DateField(null=True, blank=True)
103-
104-
class Meta:
105-
app_label = 'test_app'
106-
db_table = 'django_author'
107-
108-
# Store Author first so it's available for Book's ForeignKey
109-
TestDjango.Author = Author
110-
111-
class Book(models.Model):
112-
"""Book model for relationship testing"""
113-
title = models.CharField(max_length=200)
114-
author = models.ForeignKey(TestDjango.Author, on_delete=models.CASCADE, related_name='books')
115-
publication_date = models.DateField()
116-
pages = models.IntegerField()
117-
price = models.DecimalField(max_digits=8, decimal_places=2)
118-
119-
class Meta:
120-
app_label = 'test_app'
121-
db_table = 'django_book'
122-
123-
# Store models as class attributes for easy access
124-
TestDjango.TestModel = TestModel
125-
TestDjango.DataTypeModel = DataTypeModel
126-
TestDjango.Book = Book
127-
128-
# Create tables for our test models
129-
with connection.schema_editor() as schema_editor:
130-
schema_editor.create_model(TestModel)
131-
schema_editor.create_model(DataTypeModel)
132-
schema_editor.create_model(Author)
133-
schema_editor.create_model(Book)
134-
135-
yield
136-
137-
# Clean up tables
138-
with connection.schema_editor() as schema_editor:
139-
schema_editor.delete_model(Book)
140-
schema_editor.delete_model(Author)
141-
schema_editor.delete_model(DataTypeModel)
142-
schema_editor.delete_model(TestModel)
143-
144-
@pytest.fixture(scope='class')
145-
def django_setup(self, conn_utils):
146-
"""Setup Django configuration for testing"""
147-
# Configure Django settings
148-
if not settings.configured:
149-
db_config = {
150-
'ENGINE': 'aws_advanced_python_wrapper.django.backends.mysql_connector',
151-
'NAME': conn_utils.dbname,
152-
'USER': conn_utils.user,
153-
'PASSWORD': conn_utils.password,
154-
'HOST': conn_utils.writer_cluster_host,
155-
'PORT': conn_utils.port,
156-
'OPTIONS': {
157-
'plugins': 'failover_v2,aurora_connection_tracker',
158-
'connect_timeout': 10,
159-
'autocommit': True,
160-
},
161-
}
162-
163-
settings.configure(
164-
DEBUG=True,
165-
DATABASES={'default': db_config},
166-
INSTALLED_APPS=[
167-
'django.contrib.contenttypes',
168-
'django.contrib.auth',
169-
],
170-
SECRET_KEY='test-secret-key-for-django-tests',
171-
USE_TZ=True,
172-
)
173-
174-
django.setup()
175-
setup_test_environment()
176-
177-
yield
178-
connections.close_all()
179-
180-
teardown_test_environment()
181-
53+
id = Column(Integer, primary_key=True)
54+
55+
name = Column(String(100))
56+
email = Column(String, primary_key=True)
57+
age = Column(Integer)
58+
is_active = Column(Boolean)
59+
created_at = Column(DateTime)
60+
61+
class DataTypeModel(Base):
62+
"""Model for testing various data types"""
63+
__tablename__ = 'sqlalchemy_data_type_model'
64+
65+
id = Column(Integer, primary_key=True)
66+
67+
# String fields
68+
string_field = Column(String(255))
69+
text_field = Column(Text)
70+
71+
# Numeric fields
72+
integer_field = Column(Integer)
73+
small_integer_field = Column(SmallInteger)
74+
big_integer_field = Column(BigInteger)
75+
numeric_field = Column(Numeric)
76+
float_field = Column(Float)
77+
78+
# Boolean field
79+
boolean_field = Column(Boolean)
80+
81+
# Date/Time fields
82+
date_field = Column(Date)
83+
time_field = Column(Time)
84+
datetime_field = Column(DateTime)
85+
86+
# JSON field (MySQL 5.7+)
87+
json_field = Column(JSON)
88+
89+
class Author(Base):
90+
"""Author model for relationship testing"""
91+
__tablename__ = 'sqlalchemy_author'
92+
93+
id = Column(Integer, primary_key=True)
94+
name = Column(String(100))
95+
email = Column(String)
96+
birth_date = Column(Date)
97+
98+
class Book(Base):
99+
"""Book model for relationship testing"""
100+
__tablename__ = 'sqlalchemy_book'
101+
102+
id = Column(Integer, primary_key=True)
103+
title = Column(String(200))
104+
author = Column(String, ForeignKey("Author.id"))
105+
publication_date = Column(Date)
106+
pages = Column(Integer)
107+
price = Column(Numeric)
108+
109+
@pytest.fixture(scope="class")
110+
def engine(self, conn_utils):
111+
conn_str = f'mysql+aws_wrapper_mysqlconnector://{conn_utils.user}:{conn_utils.password}@{conn_utils.writer_cluster_host}:{conn_utils.port}/{conn_utils.dbname}'
112+
engine = create_engine(conn_str)
113+
Base.metadata.create_all(engine)
114+
yield engine
115+
Base.metadata.drop_all(engine)
116+
117+
@pytest.fixture(scope="class")
118+
def Session(self, engine):
119+
Session = sessionmaker(bind=engine)
120+
yield Session
121+
122+
@pytest.fixture(scope="class")
123+
def session(self, Session):
124+
session = Session()
125+
yield session
126+
session.rollback()
127+
session.close()
128+
129+
'''
182130
def test_django_backend_configuration(self, test_environment: TestEnvironment, django_models):
183131
"""Test Django backend configuration with empty plugins"""
184132
# Verify that the connection is using the AWS wrapper
185133
assert hasattr(connection, 'connection')
186134
187135
# Test basic connection functionality
188136
assert self.TestModel.objects.count() == 0
137+
'''
189138

190-
def test_django_basic_model_operations(self, test_environment: TestEnvironment, django_models):
139+
def test_sqlalchemy_basic_model_operations(self, session, test_environment: TestEnvironment):
191140
"""Test basic Django ORM operations (CRUD)"""
192-
TestModel = self.TestModel
193-
194-
# Ensure clean slate
195-
TestModel.objects.all().delete()
196141

197142
# Create
198-
test_obj = TestModel.objects.create(
143+
test_obj = TestModel(
199144
name="John Doe",
200145
email="john@example.com",
201146
age=30,
202147
is_active=True
203148
)
149+
session.add(test_obj)
150+
session.commit()
204151
assert test_obj.id is not None
205152
assert test_obj.name == "John Doe"
206153

207154
# Read
208-
retrieved_obj = TestModel.objects.get(id=test_obj.id)
155+
retrieved_obj = session.query(TestModel).filter(TestModel.id == test_obj.id).first()
209156
assert retrieved_obj.name == "John Doe"
210157
assert retrieved_obj.email == "john@example.com"
211158
assert retrieved_obj.age == 30
@@ -214,16 +161,18 @@ def test_django_basic_model_operations(self, test_environment: TestEnvironment,
214161
# Update
215162
retrieved_obj.name = "Jane Doe"
216163
retrieved_obj.age = 25
217-
retrieved_obj.save()
164+
session.commit()
218165

219-
updated_obj = TestModel.objects.get(id=test_obj.id)
166+
updated_obj = session.query(TestModel).filter(TestModel.id == test_obj.id).first()
220167
assert updated_obj.name == "Jane Doe"
221168
assert updated_obj.age == 25
222169

223170
# Delete
224-
updated_obj.delete()
225-
assert TestModel.objects.filter(id=test_obj.id).count() == 0
171+
session.delete(updated_obj)
172+
session.commit()
173+
assert session.query(TestModel).filter(TestModel.id == test_obj.id).count() == 0
226174

175+
'''
227176
def test_django_queryset_operations(self, test_environment: TestEnvironment, django_models):
228177
"""Test Django QuerySet operations"""
229178
TestModel = self.TestModel

tests/integration/container/utils/test_database_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __init__(self, database_info: Dict[str, Any]) -> None:
4242

4343
self._username = typing.cast('str', database_info.get("username"))
4444
self._password = typing.cast('str', database_info.get("password"))
45-
self._default_db_name = typing.cast('str', database_info.get("defaultDbName"))
45+
self._default_db_name = "mysqldb"
4646
self._cluster_endpoint = typing.cast('str', database_info.get("clusterEndpoint"))
4747
self._cluster_endpoint_port = typing.cast('int', database_info.get("clusterEndpointPort"))
4848
self._cluster_read_only_endpoint = typing.cast('str', database_info.get("clusterReadOnlyEndpoint"))

tests/integration/container/utils/test_environment_request.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def get_features(self) -> Set[TestEnvironmentFeatures]:
6363
return self._features
6464

6565
def get_num_of_instances(self) -> int:
66-
return self._num_of_instances
66+
return 3
6767

6868
def get_display_name(self) -> str:
6969
return "Test environment [{0}, {1}, {2}, {3}, {4}, {5}]".format(

0 commit comments

Comments
 (0)