Skip to content

Commit e2135c2

Browse files
committed
Update tests to improve coverage
1 parent 5f55a0c commit e2135c2

File tree

4 files changed

+139
-195
lines changed

4 files changed

+139
-195
lines changed

tests/test_delete.py

Lines changed: 109 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,15 @@ async def test_delete_model_with_commit(db: AsyncSession, sample_ins: list[Ins],
5252
async def test_delete_model_by_column_basic(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
5353
item = sample_ins[3]
5454

55-
async with db.begin():
56-
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, name=item.name)
55+
before_exists = await crud_ins.exists(db, name=item.name)
56+
assert before_exists is True
5757

58-
assert count >= 0
58+
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, commit=True, name=item.name)
59+
60+
assert count > 0
61+
62+
after_exists = await crud_ins.exists(db, name=item.name)
63+
assert after_exists is False
5964

6065

6166
@pytest.mark.asyncio
@@ -68,29 +73,45 @@ async def test_delete_model_by_column_not_found(db: AsyncSession, crud_ins: CRUD
6873

6974
@pytest.mark.asyncio
7075
async def test_delete_model_by_column_allow_multiple(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
71-
async with db.begin():
72-
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, is_deleted=False)
76+
before_count = await crud_ins.count(db, is_deleted=False)
77+
assert before_count > 0
7378

74-
assert count >= 0
79+
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, commit=True, is_deleted=False)
80+
81+
assert count == before_count
82+
83+
after_count = await crud_ins.count(db, is_deleted=False)
84+
assert after_count == 0
7585

7686

7787
@pytest.mark.asyncio
7888
async def test_delete_model_by_column_with_flush(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
7989
item = sample_ins[4]
8090

81-
async with db.begin():
82-
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, flush=True, name=item.name)
91+
before_exists = await crud_ins.exists(db, name=item.name)
92+
assert before_exists is True
8393

84-
assert count >= 0
94+
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, commit=True, name=item.name)
95+
96+
assert count > 0
97+
98+
after_exists = await crud_ins.exists(db, name=item.name)
99+
assert after_exists is False
85100

86101

87102
@pytest.mark.asyncio
88103
async def test_delete_model_by_column_with_commit(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
89104
item = sample_ins[5]
90105

106+
before_exists = await crud_ins.exists(db, name=item.name)
107+
assert before_exists is True
108+
91109
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, commit=True, name=item.name)
92110

93-
assert count >= 0
111+
assert count > 0
112+
113+
after_exists = await crud_ins.exists(db, name=item.name)
114+
assert after_exists is False
94115

95116

96117
@pytest.mark.asyncio
@@ -104,7 +125,9 @@ async def test_delete_model_by_column_no_filters_error(db: AsyncSession, crud_in
104125
async def test_delete_model_by_column_multiple_results_error(
105126
db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]
106127
):
107-
with pytest.raises(Exception):
128+
from sqlalchemy_crud_plus.errors import MultipleResultsError
129+
130+
with pytest.raises(MultipleResultsError):
108131
async with db.begin():
109132
await crud_ins.delete_model_by_column(db, is_deleted=False)
110133

@@ -130,20 +153,22 @@ async def test_logical_delete_single_record(db: AsyncSession, sample_ins: list[I
130153

131154
@pytest.mark.asyncio
132155
async def test_logical_delete_multiple_records(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
133-
async with db.begin():
134-
count = await crud_ins.delete_model_by_column(
135-
db,
136-
logical_deletion=True,
137-
deleted_flag_column='is_deleted',
138-
allow_multiple=True,
139-
is_deleted=False,
140-
)
156+
before_count = await crud_ins.count(db, is_deleted=False)
157+
assert before_count > 0
141158

142-
assert count >= 0
159+
count = await crud_ins.delete_model_by_column(
160+
db,
161+
logical_deletion=True,
162+
deleted_flag_column='is_deleted',
163+
allow_multiple=True,
164+
commit=True,
165+
is_deleted=False,
166+
)
143167

144-
async with db.begin():
145-
remaining_false = await crud_ins.select_models(db, is_deleted=False)
146-
assert len(remaining_false) >= 0
168+
assert count == before_count
169+
170+
remaining_false = await crud_ins.select_models(db, is_deleted=False)
171+
assert len(remaining_false) == 0
147172

148173

149174
@pytest.mark.asyncio
@@ -164,22 +189,22 @@ async def test_logical_delete_with_custom_column(db: AsyncSession, sample_ins: l
164189

165190
@pytest.mark.asyncio
166191
async def test_logical_delete_with_filters(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
167-
async with db.begin():
168-
count = await crud_ins.delete_model_by_column(
169-
db,
170-
logical_deletion=True,
171-
deleted_flag_column='is_deleted',
172-
allow_multiple=True,
173-
name__like='item_%',
174-
id__gt=3,
175-
)
192+
await crud_ins.count(db, name__like='item_%', id__gt=3, is_deleted=False)
176193

177-
assert count >= 0
194+
count = await crud_ins.delete_model_by_column(
195+
db,
196+
logical_deletion=True,
197+
deleted_flag_column='is_deleted',
198+
allow_multiple=True,
199+
commit=True,
200+
name__like='item_%',
201+
id__gt=3,
202+
)
178203

179-
async with db.begin():
180-
deleted_items = await crud_ins.select_models(db, name__like='item_%', id__gt=3, is_deleted=True)
204+
assert count >= 0
181205

182-
assert len(deleted_items) >= 0
206+
deleted_items = await crud_ins.select_models(db, name__like='item_%', id__gt=3, is_deleted=True)
207+
assert len(deleted_items) >= count
183208

184209

185210
@pytest.mark.asyncio
@@ -234,20 +259,23 @@ async def test_logical_delete_no_matching_records(db: AsyncSession, crud_ins: CR
234259

235260
@pytest.mark.asyncio
236261
async def test_logical_delete_already_deleted_records(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
237-
async with db.begin():
238-
await crud_ins.delete_model_by_column(
239-
db, logical_deletion=True, deleted_flag_column='is_deleted', allow_multiple=True, id__le=3
240-
)
262+
first_count = await crud_ins.delete_model_by_column(
263+
db, logical_deletion=True, deleted_flag_column='is_deleted', allow_multiple=True, commit=True, id__le=3
264+
)
265+
assert first_count >= 0
241266

242-
async with db.begin():
243-
count = await crud_ins.delete_model_by_column(
244-
db,
245-
logical_deletion=True,
246-
deleted_flag_column='is_deleted',
247-
allow_multiple=True,
248-
id__le=3,
249-
is_deleted=True,
250-
)
267+
already_deleted_count = await crud_ins.count(db, id__le=3, is_deleted=True)
268+
assert already_deleted_count >= first_count
269+
270+
count = await crud_ins.delete_model_by_column(
271+
db,
272+
logical_deletion=True,
273+
deleted_flag_column='is_deleted',
274+
allow_multiple=True,
275+
commit=True,
276+
id__le=3,
277+
is_deleted=True,
278+
)
251279

252280
assert count >= 0
253281

@@ -295,23 +323,22 @@ async def test_logical_delete_single_but_multiple_found(
295323
async def test_logical_delete_affects_count(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
296324
initial_count = await crud_ins.count(db, is_deleted=False)
297325

326+
to_delete_count = await crud_ins.count(db, id__le=2, is_deleted=False)
327+
298328
deleted_count = await crud_ins.delete_model_by_column(
299329
db,
300330
logical_deletion=True,
301331
deleted_flag_column='is_deleted',
302332
allow_multiple=True,
303333
commit=True,
304334
id__le=2,
335+
is_deleted=False,
305336
)
306337

307338
final_count = await crud_ins.count(db, is_deleted=False)
308339

309-
# 检查是否至少删除了一条记录
310-
assert deleted_count >= 0
311-
312-
# 如果删除了记录,则最终计数应该小于或等于初始计数
313-
if deleted_count > 0:
314-
assert final_count <= initial_count
340+
assert deleted_count == to_delete_count
341+
assert final_count == initial_count - deleted_count
315342

316343

317344
@pytest.mark.asyncio
@@ -359,7 +386,6 @@ async def test_logical_delete_with_select_models(db: AsyncSession, sample_ins: l
359386

360387
@pytest.mark.asyncio
361388
async def test_delete_model_by_column_with_deleted_at(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
362-
# 使用数据库中存在的项目
363389
item = sample_ins[6]
364390

365391
async with db.begin():
@@ -378,7 +404,6 @@ async def test_delete_model_by_column_with_deleted_at(db: AsyncSession, sample_i
378404
async def test_delete_model_by_column_without_deleted_at_column(
379405
db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]
380406
):
381-
# 使用数据库中存在的项目
382407
item = sample_ins[7]
383408

384409
async with db.begin():
@@ -390,3 +415,30 @@ async def test_delete_model_by_column_without_deleted_at_column(
390415
updated_item = await crud_ins.select_model(db, item.id)
391416
assert updated_item is not None
392417
assert updated_item.is_deleted is True
418+
419+
420+
@pytest.mark.asyncio
421+
async def test_delete_model_by_column_with_custom_deleted_at_column(
422+
db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]
423+
):
424+
from datetime import datetime, timezone
425+
426+
item = sample_ins[8]
427+
428+
async with db.begin():
429+
count = await crud_ins.delete_model_by_column(
430+
db,
431+
logical_deletion=True,
432+
deleted_flag_column='is_deleted',
433+
deleted_at_column='updated_time',
434+
deleted_at_factory=datetime.now(timezone.utc),
435+
id=item.id,
436+
)
437+
438+
assert count == 1
439+
440+
async with db.begin():
441+
updated_item = await crud_ins.select_model(db, item.id)
442+
assert updated_item is not None
443+
assert updated_item.is_deleted is True
444+
assert updated_item.updated_time is not None

tests/test_filters.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,23 @@ async def test_filter_like(db: AsyncSession, sample_ins: list[Ins], crud_ins: CR
113113
async def test_filter_not_like(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
114114
results = await crud_ins.select_models(db, name__not_like='nonexistent_%')
115115

116-
assert len(results) >= 0
116+
assert len(results) > 0
117+
assert all('nonexistent_' not in r.name for r in results)
117118

118119

119120
@pytest.mark.asyncio
120121
async def test_filter_ilike(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
121122
results = await crud_ins.select_models(db, name__ilike='ITEM_%')
122123

123-
assert len(results) >= 0
124+
assert len(results) > 0
125+
assert all(r.name.lower().startswith('item_') for r in results)
124126

125127

126128
@pytest.mark.asyncio
127129
async def test_filter_not_ilike(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
128130
results = await crud_ins.select_models(db, name__not_ilike='ITEM_%')
129131

130-
assert len(results) >= 0
132+
assert all(not r.name.lower().startswith('item_') for r in results)
131133

132134

133135
@pytest.mark.asyncio
@@ -155,23 +157,23 @@ async def test_filter_contains(db: AsyncSession, sample_ins: list[Ins], crud_ins
155157
async def test_filter_match(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
156158
try:
157159
results = await crud_ins.select_models(db, name__match='item')
158-
assert len(results) >= 0
159-
except Exception:
160-
assert True
160+
assert isinstance(results, list)
161+
except Exception as e:
162+
assert 'match' in str(e).lower() or 'not supported' in str(e).lower()
161163

162164

163165
@pytest.mark.asyncio
164166
async def test_filter_concat(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
165167
results = await crud_ins.select_models(db, name__concat='_test')
166168

167-
assert len(results) >= 0
169+
assert isinstance(results, list)
168170

169171

170172
@pytest.mark.asyncio
171173
async def test_filter_add(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
172174
results = await crud_ins.select_models(db, id__add=1)
173175

174-
assert len(results) >= 0
176+
assert isinstance(results, list)
175177

176178

177179
@pytest.mark.asyncio
@@ -255,7 +257,9 @@ async def test_filter_rmod(db: AsyncSession, sample_ins: list[Ins], crud_ins: CR
255257
async def test_filter_or_same_field_list_values(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
256258
results = await crud_ins.select_models(db, __or__={'is_deleted': [True, False]})
257259

258-
assert len(results) >= 0
260+
total_count = await crud_ins.count(db)
261+
assert len(results) == total_count
262+
assert all(r.is_deleted in [True, False] for r in results)
259263

260264

261265
@pytest.mark.asyncio
@@ -264,14 +268,16 @@ async def test_filter_or_different_fields_single_values(
264268
):
265269
results = await crud_ins.select_models(db, __or__={'is_deleted': True, 'id__gt': 5})
266270

267-
assert len(results) >= 0
271+
assert len(results) > 0
272+
assert all(r.is_deleted is True or r.id > 5 for r in results)
268273

269274

270275
@pytest.mark.asyncio
271276
async def test_filter_or_with_operators(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
272277
results = await crud_ins.select_models(db, __or__={'name__like': 'item_%', 'id__lt': 3})
273278

274-
assert len(results) >= 0
279+
assert len(results) > 0
280+
assert all('item_' in r.name or r.id < 3 for r in results)
275281

276282

277283
@pytest.mark.asyncio

0 commit comments

Comments
 (0)