forked from kaw393939/event-manager-qa-onboarding
-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathconftest.py
More file actions
263 lines (234 loc) · 8.5 KB
/
Copy pathconftest.py
File metadata and controls
263 lines (234 loc) · 8.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
"""
File: test_database_operations.py
Overview:
This Python test file utilizes pytest to manage database states and HTTP clients for testing a web application built with FastAPI and SQLAlchemy. It includes detailed fixtures to mock the testing environment, ensuring each test is run in isolation with a consistent setup.
Fixtures:
- `async_client`: Manages an asynchronous HTTP client for testing interactions with the FastAPI application.
- `db_session`: Handles database transactions to ensure a clean database state for each test.
- User fixtures (`user`, `locked_user`, `verified_user`, etc.): Set up various user states to test different behaviors under diverse conditions.
- `token`: Generates an authentication token for testing secured endpoints.
- `initialize_database`: Prepares the database at the session start.
- `setup_database`: Sets up and tears down the database before and after each test.
"""
# Standard library imports
from builtins import range
from datetime import datetime
from unittest.mock import patch
from uuid import uuid4
# Third-party imports
import pytest
from fastapi.testclient import TestClient
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, scoped_session
from faker import Faker
# Application-specific imports
from app.main import app
from app.database import Base, Database
from app.models.user_model import User, UserRole
from app.dependencies import get_db, get_settings
from app.utils.security import hash_password
from app.utils.template_manager import TemplateManager
from app.services.email_service import EmailService
from app.services.jwt_service import create_access_token
fake = Faker()
settings = get_settings()
TEST_DATABASE_URL = settings.database_url.replace("postgresql://", "postgresql+asyncpg://")
engine = create_async_engine(TEST_DATABASE_URL, echo=settings.debug)
AsyncTestingSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
AsyncSessionScoped = scoped_session(AsyncTestingSessionLocal)
@pytest.fixture
def email_service():
# Assuming the TemplateManager does not need any arguments for initialization
template_manager = TemplateManager()
email_service = EmailService(template_manager=template_manager)
return email_service
# this is what creates the http client for your api tests
@pytest.fixture(scope="function")
async def async_client(db_session):
async with AsyncClient(app=app, base_url="http://testserver") as client:
app.dependency_overrides[get_db] = lambda: db_session
try:
yield client
finally:
app.dependency_overrides.clear()
@pytest.fixture(scope="session", autouse=True)
def initialize_database():
try:
Database.initialize(settings.database_url)
except Exception as e:
pytest.fail(f"Failed to initialize the database: {str(e)}")
# this function setup and tears down (drops tales) for each test function, so you have a clean database for each test.
@pytest.fixture(scope="function", autouse=True)
async def setup_database():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
async with engine.begin() as conn:
# you can comment out this line during development if you are debugging a single test
await conn.run_sync(Base.metadata.drop_all)
await engine.dispose()
@pytest.fixture(scope="function")
async def db_session(setup_database):
async with AsyncSessionScoped() as session:
try:
yield session
finally:
await session.close()
@pytest.fixture(scope="function")
async def locked_user(db_session):
unique_email = fake.email()
user_data = {
"nickname": fake.user_name(),
"first_name": fake.first_name(),
"last_name": fake.last_name(),
"email": unique_email,
"hashed_password": hash_password("MySuperPassword$1234"),
"role": UserRole.AUTHENTICATED,
"email_verified": False,
"is_locked": True,
"failed_login_attempts": settings.max_login_attempts,
}
user = User(**user_data)
db_session.add(user)
await db_session.commit()
return user
@pytest.fixture(scope="function")
async def user(db_session):
user_data = {
"nickname": fake.user_name(),
"first_name": fake.first_name(),
"last_name": fake.last_name(),
"email": fake.email(),
"hashed_password": hash_password("MySuperPassword$1234"),
"role": UserRole.AUTHENTICATED,
"email_verified": False,
"is_locked": False,
}
user = User(**user_data)
db_session.add(user)
await db_session.commit()
return user
@pytest.fixture(scope="function")
async def verified_user(db_session):
user_data = {
"nickname": fake.user_name(),
"first_name": fake.first_name(),
"last_name": fake.last_name(),
"email": fake.email(),
"hashed_password": hash_password("MySuperPassword$1234"),
"role": UserRole.AUTHENTICATED,
"email_verified": True,
"is_locked": False,
}
user = User(**user_data)
db_session.add(user)
await db_session.commit()
return user
@pytest.fixture(scope="function")
async def unverified_user(db_session):
user_data = {
"nickname": fake.user_name(),
"first_name": fake.first_name(),
"last_name": fake.last_name(),
"email": fake.email(),
"hashed_password": hash_password("MySuperPassword$1234"),
"role": UserRole.AUTHENTICATED,
"email_verified": False,
"is_locked": False,
}
user = User(**user_data)
db_session.add(user)
await db_session.commit()
return user
@pytest.fixture(scope="function")
async def users_with_same_role_50_users(db_session):
users = []
for _ in range(50):
user_data = {
"nickname": fake.user_name(),
"first_name": fake.first_name(),
"last_name": fake.last_name(),
"email": fake.email(),
"hashed_password": fake.password(),
"role": UserRole.AUTHENTICATED,
"email_verified": False,
"is_locked": False,
}
user = User(**user_data)
db_session.add(user)
users.append(user)
await db_session.commit()
return users
@pytest.fixture
async def admin_user(db_session: AsyncSession):
user = User(
nickname="admin_user",
email="admin@example.com",
first_name="John",
last_name="Doe",
hashed_password="securepassword",
role=UserRole.ADMIN,
is_locked=False,
)
db_session.add(user)
await db_session.commit()
return user
@pytest.fixture
async def manager_user(db_session: AsyncSession):
user = User(
nickname="manager_john",
first_name="John",
last_name="Doe",
email="manager_user@example.com",
hashed_password="securepassword",
role=UserRole.MANAGER,
is_locked=False,
)
db_session.add(user)
await db_session.commit()
return user
# Fixtures for common test data
@pytest.fixture
def user_base_data():
return {
"username": "john_doe_123",
"email": "john.doe@example.com",
"full_name": "John Doe",
"bio": "I am a software engineer with over 5 years of experience.",
"profile_picture_url": "https://example.com/profile_pictures/john_doe.jpg"
}
@pytest.fixture
def user_base_data_invalid():
return {
"username": "john_doe_123",
"email": "john.doe.example.com",
"full_name": "John Doe",
"bio": "I am a software engineer with over 5 years of experience.",
"profile_picture_url": "https://example.com/profile_pictures/john_doe.jpg"
}
@pytest.fixture
def user_create_data(user_base_data):
return {**user_base_data, "password": "SecurePassword123!"}
@pytest.fixture
def user_update_data():
return {
"email": "john.doe.new@example.com",
"full_name": "John H. Doe",
"bio": "I specialize in backend development with Python and Node.js.",
"profile_picture_url": "https://example.com/profile_pictures/john_doe_updated.jpg"
}
@pytest.fixture
def user_response_data():
return {
"id": "unique-id-string",
"username": "testuser",
"email": "test@example.com",
"last_login_at": datetime.now(),
"created_at": datetime.now(),
"updated_at": datetime.now(),
"links": []
}
@pytest.fixture
def login_request_data():
return {"username": "john_doe_123", "password": "SecurePassword123!"}