55import pytest
66import pytest_asyncio
77
8+ from sqlalchemy import insert
89from sqlalchemy .ext .asyncio import AsyncSession , async_sessionmaker , create_async_engine
910
1011from sqlalchemy_crud_plus import CRUDPlus
11- from tests .models .basic import Base as BasicBase
12- from tests .models .basic import Ins , InsPks
12+ from tests .models .basic import Base , Ins , InsPks
1313from tests .models .relations import RelationBase , RelCategory , RelPost , RelProfile , RelRole , RelUser , user_role
1414from tests .schemas .relations import RelPostCreate , RelProfileCreate , RelRoleCreate , RelUserCreate
1515
16- # Database configuration
1716_async_engine = create_async_engine ('sqlite+aiosqlite:///:memory:' , future = True , echo = False )
18- _async_session_factory = async_sessionmaker (_async_engine , autoflush = False , expire_on_commit = False )
17+ _async_db_session = async_sessionmaker (_async_engine , autoflush = False , expire_on_commit = False )
1918
2019
21- @pytest_asyncio .fixture (scope = 'function ' , autouse = True )
22- async def setup_database () -> AsyncGenerator [ None , None ] :
23- """Setup and teardown database for each test function ."""
20+ @pytest_asyncio .fixture (scope = 'session ' , autouse = True )
21+ async def setup_database ():
22+ """Set up the test database ."""
2423 async with _async_engine .begin () as conn :
25- await conn .run_sync (BasicBase .metadata .create_all )
24+ await conn .run_sync (Base .metadata .create_all )
2625 await conn .run_sync (RelationBase .metadata .create_all )
2726
28- yield
29-
30- async with _async_engine .begin () as conn :
31- await conn .run_sync (BasicBase .metadata .drop_all )
32- await conn .run_sync (RelationBase .metadata .drop_all )
33-
34-
35- @pytest_asyncio .fixture
36- async def db_session () -> AsyncGenerator [AsyncSession , None ]:
37- """Provide a database session for testing."""
38- async with _async_session_factory () as session :
39- yield session
40-
41-
42- @pytest_asyncio .fixture
43- async def db_session_factory () -> AsyncGenerator [async_sessionmaker [AsyncSession ], None ]:
44- """Provide a session factory for testing."""
45- yield _async_session_factory
46-
4727
4828@pytest .fixture
4929def crud_ins () -> CRUDPlus [Ins ]:
@@ -58,166 +38,158 @@ def crud_ins_pks() -> CRUDPlus[InsPks]:
5838
5939
6040@pytest_asyncio .fixture
61- async def populated_db (db_session : AsyncSession , crud_ins : CRUDPlus [Ins ]) -> list [Ins ]:
41+ async def async_db_session () -> AsyncGenerator [AsyncSession , None ]:
42+ """Provide a database session for testing."""
43+ async with _async_db_session () as session :
44+ yield session
45+
46+
47+ @pytest_asyncio .fixture
48+ async def populated_db (async_db_session : AsyncSession , crud_ins : CRUDPlus [Ins ]) -> list [Ins ]:
6249 """Provide a database populated with test data."""
63- async with db_session .begin ():
50+ async with async_db_session .begin ():
6451 test_data = [Ins (name = f'item_{ i } ' , del_flag = (i % 2 == 0 )) for i in range (1 , 11 )]
65- db_session .add_all (test_data )
66- await db_session .flush ()
52+ async_db_session .add_all (test_data )
6753 return test_data
6854
6955
7056@pytest_asyncio .fixture
71- async def populated_db_pks (db_session : AsyncSession ) -> dict [str , list [InsPks ]]:
57+ async def populated_db_pks (async_db_session : AsyncSession ) -> dict [str , list [InsPks ]]:
7258 """Provide a database populated with composite key test data."""
73- async with db_session .begin ():
59+ async with async_db_session .begin ():
7460 men_data = [InsPks (id = i , name = f'man_{ i } ' , sex = 'men' ) for i in range (1 , 4 )]
75- women_data = [InsPks (id = i , name = f'woman_{ i } ' , sex = 'women' ) for i in range (4 , 7 )]
61+ women_data = [InsPks (id = i , name = f'woman_{ i } ' , sex = 'women' ) for i in range (1 , 4 )]
7662 all_data = men_data + women_data
7763
78- db_session .add_all (all_data )
79- await db_session .flush ()
64+ async_db_session .add_all (all_data )
65+ await async_db_session .flush ()
8066
8167 return {'men' : men_data , 'women' : women_data , 'all' : all_data }
8268
8369
8470@pytest .fixture
85- def rel_user_crud () -> CRUDPlus [RelUser ]:
71+ def rel_crud_user () -> CRUDPlus [RelUser ]:
8672 """Provide CRUD instance for RelUser model."""
8773 return CRUDPlus (RelUser )
8874
8975
9076@pytest .fixture
91- def rel_post_crud () -> CRUDPlus [RelPost ]:
77+ def rel_crud_post () -> CRUDPlus [RelPost ]:
9278 """Provide CRUD instance for RelPost model."""
9379 return CRUDPlus (RelPost )
9480
9581
9682@pytest .fixture
97- def rel_profile_crud () -> CRUDPlus [RelProfile ]:
83+ def rel_crud_profile () -> CRUDPlus [RelProfile ]:
9884 """Provide CRUD instance for RelProfile model."""
9985 return CRUDPlus (RelProfile )
10086
10187
10288@pytest .fixture
103- def rel_category_crud () -> CRUDPlus [RelCategory ]:
89+ def rel_crud_category () -> CRUDPlus [RelCategory ]:
10490 """Provide CRUD instance for RelCategory model."""
10591 return CRUDPlus (RelCategory )
10692
10793
10894@pytest .fixture
109- def rel_role_crud () -> CRUDPlus [RelRole ]:
95+ def rel_crud_role () -> CRUDPlus [RelRole ]:
11096 """Provide CRUD instance for RelRole model."""
11197 return CRUDPlus (RelRole )
11298
11399
114100@pytest_asyncio .fixture
115- async def rel_sample_users (db_session : AsyncSession ) -> list [RelUser ]:
101+ async def rel_sample_users (async_db_session : AsyncSession ) -> list [RelUser ]:
116102 """Create sample relation users."""
117- async with db_session .begin ():
103+ async with async_db_session .begin ():
118104 users = []
119105 for i in range (1 , 4 ):
120106 user_data = RelUserCreate (name = f'user_{ i } ' )
121107 user = RelUser (** user_data .model_dump ())
122- db_session .add (user )
108+ async_db_session .add (user )
123109 users .append (user )
124- await db_session .flush ()
125110 return users
126111
127112
128113@pytest_asyncio .fixture
129- async def rel_sample_profiles (db_session : AsyncSession , rel_sample_users : list [RelUser ]) -> list [RelProfile ]:
114+ async def rel_sample_profiles (async_db_session : AsyncSession , rel_sample_users : list [RelUser ]) -> list [RelProfile ]:
130115 """Create sample relation profiles."""
131- async with db_session .begin ():
116+ async with async_db_session .begin ():
132117 profiles = []
133- for i , user in enumerate (rel_sample_users [:2 ]): # Only first 2 users get profiles
118+ for i , user in enumerate (rel_sample_users [:2 ]):
134119 profile_data = RelProfileCreate (bio = f'Bio for { user .name } ' )
135120 profile = RelProfile (user_id = user .id , ** profile_data .model_dump ())
136- db_session .add (profile )
121+ async_db_session .add (profile )
137122 profiles .append (profile )
138- await db_session .flush ()
139123 return profiles
140124
141125
142126@pytest_asyncio .fixture
143- async def rel_sample_categories (db_session : AsyncSession ) -> list [RelCategory ]:
127+ async def rel_sample_categories (async_db_session : AsyncSession ) -> list [RelCategory ]:
144128 """Create sample relation categories."""
145- async with db_session .begin ():
146- categories = []
147- # Root categories
148- tech = RelCategory (name = 'Technology' )
149- science = RelCategory (name = 'Science' )
150- db_session .add_all ([tech , science ])
151- await db_session .flush ()
152-
153- # Sub categories
129+ async with async_db_session .begin ():
130+ tech = RelCategory (name = 'Technology' , parent_id = None )
131+ science = RelCategory (name = 'Science' , parent_id = None )
132+ async_db_session .add_all ([tech , science ])
133+ await async_db_session .flush ()
134+
154135 programming = RelCategory (name = 'Programming' , parent_id = tech .id )
155136 ai = RelCategory (name = 'AI' , parent_id = tech .id )
156- db_session .add_all ([programming , ai ])
157- await db_session .flush ()
158-
137+ async_db_session .add_all ([programming , ai ])
159138 categories = [tech , science , programming , ai ]
160139 return categories
161140
162141
163142@pytest_asyncio .fixture
164143async def rel_sample_posts (
165- db_session : AsyncSession , rel_sample_users : list [RelUser ], rel_sample_categories : list [RelCategory ]
144+ async_db_session : AsyncSession , rel_sample_users : list [RelUser ], rel_sample_categories : list [RelCategory ]
166145) -> list [RelPost ]:
167146 """Create sample relation posts."""
168- async with db_session .begin ():
147+ async with async_db_session .begin ():
169148 posts = []
170149 for i in range (6 ):
171150 post_data = RelPostCreate (
172151 title = f'Post { i + 1 } ' ,
173152 category_id = rel_sample_categories [i % len (rel_sample_categories )].id if i < 4 else None ,
174153 )
175154 post = RelPost (author_id = rel_sample_users [i % len (rel_sample_users )].id , ** post_data .model_dump ())
176- db_session .add (post )
155+ async_db_session .add (post )
177156 posts .append (post )
178- await db_session .flush ()
179157 return posts
180158
181159
182160@pytest_asyncio .fixture
183- async def rel_sample_roles (db_session : AsyncSession ) -> list [RelRole ]:
161+ async def rel_sample_roles (async_db_session : AsyncSession ) -> list [RelRole ]:
184162 """Create sample relation roles."""
185- async with db_session .begin ():
163+ async with async_db_session .begin ():
186164 roles = []
187- for role_name in ['admin' , 'editor' , 'viewer' ]:
165+ for role_name in ['admin' , 'editor' ]:
188166 role_data = RelRoleCreate (name = role_name )
189167 role = RelRole (** role_data .model_dump ())
190- db_session .add (role )
168+ async_db_session .add (role )
191169 roles .append (role )
192- await db_session .flush ()
193170 return roles
194171
195172
196173@pytest_asyncio .fixture
197174async def rel_sample_data (
198- db_session : AsyncSession ,
175+ async_db_session : AsyncSession ,
199176 rel_sample_users : list [RelUser ],
200177 rel_sample_profiles : list [RelProfile ],
201178 rel_sample_categories : list [RelCategory ],
202179 rel_sample_posts : list [RelPost ],
203180 rel_sample_roles : list [RelRole ],
204181) -> dict :
205182 """Create complete relation sample data with relationships."""
206- async with db_session .begin ():
207- # Create user-role relationships
208- await db_session .execute (
209- user_role .insert ().values (
183+ async with async_db_session .begin ():
184+ await async_db_session .execute (
185+ insert (user_role ).values (
210186 [
211- {'user_id' : rel_sample_users [0 ].id , 'role_id' : rel_sample_roles [0 ].id }, # user_1 is admin
212- {'user_id' : rel_sample_users [1 ].id , 'role_id' : rel_sample_roles [1 ].id }, # user_2 is editor
213- {'user_id' : rel_sample_users [0 ].id , 'role_id' : rel_sample_roles [1 ].id }, # user_1 is also editor
187+ {'user_id' : rel_sample_users [0 ].id , 'role_id' : rel_sample_roles [0 ].id },
188+ {'user_id' : rel_sample_users [1 ].id , 'role_id' : rel_sample_roles [1 ].id },
214189 ]
215190 )
216191 )
217192
218- await db_session .flush ()
219- await db_session .commit ()
220-
221193 return {
222194 'users' : rel_sample_users ,
223195 'profiles' : rel_sample_profiles ,
0 commit comments