Skip to content

Commit 9222c4d

Browse files
authored
Update tests to improve coverage (#82)
* Update tests to improve coverage * Update tests * Fix missing coverage
1 parent 5f55a0c commit 9222c4d

File tree

6 files changed

+265
-214
lines changed

6 files changed

+265
-214
lines changed

tests/test_delete.py

Lines changed: 118 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ async def test_delete_model_by_id_not_found(db: AsyncSession, crud_ins: CRUDPlus
3333
async def test_delete_model_with_flush(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
3434
item = sample_ins[1]
3535

36-
async with db.begin():
37-
count = await crud_ins.delete_model(db, item.id, flush=True)
36+
count = await crud_ins.delete_model(db, item.id, flush=True)
3837

3938
assert count == 1
4039

@@ -52,10 +51,15 @@ async def test_delete_model_with_commit(db: AsyncSession, sample_ins: list[Ins],
5251
async def test_delete_model_by_column_basic(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
5352
item = sample_ins[3]
5453

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

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

6064

6165
@pytest.mark.asyncio
@@ -68,29 +72,45 @@ async def test_delete_model_by_column_not_found(db: AsyncSession, crud_ins: CRUD
6872

6973
@pytest.mark.asyncio
7074
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)
75+
before_count = await crud_ins.count(db, is_deleted=False)
76+
assert before_count > 0
7377

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

7685

7786
@pytest.mark.asyncio
7887
async def test_delete_model_by_column_with_flush(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
7988
item = sample_ins[4]
8089

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

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

86100

87101
@pytest.mark.asyncio
88102
async def test_delete_model_by_column_with_commit(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
89103
item = sample_ins[5]
90104

105+
before_exists = await crud_ins.exists(db, name=item.name)
106+
assert before_exists is True
107+
91108
count = await crud_ins.delete_model_by_column(db, allow_multiple=True, commit=True, name=item.name)
92109

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

95115

96116
@pytest.mark.asyncio
@@ -104,7 +124,9 @@ async def test_delete_model_by_column_no_filters_error(db: AsyncSession, crud_in
104124
async def test_delete_model_by_column_multiple_results_error(
105125
db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]
106126
):
107-
with pytest.raises(Exception):
127+
from sqlalchemy_crud_plus.errors import MultipleResultsError
128+
129+
with pytest.raises(MultipleResultsError):
108130
async with db.begin():
109131
await crud_ins.delete_model_by_column(db, is_deleted=False)
110132

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

131153
@pytest.mark.asyncio
132154
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-
)
155+
before_count = await crud_ins.count(db, is_deleted=False)
156+
assert before_count > 0
141157

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

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

148172

149173
@pytest.mark.asyncio
@@ -164,37 +188,36 @@ async def test_logical_delete_with_custom_column(db: AsyncSession, sample_ins: l
164188

165189
@pytest.mark.asyncio
166190
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-
)
191+
await crud_ins.count(db, name__like='item_%', id__gt=3, is_deleted=False)
176192

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

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

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

184208

185209
@pytest.mark.asyncio
186210
async def test_logical_delete_with_flush(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
187211
item = sample_ins[2]
188212

189-
async with db.begin():
190-
count = await crud_ins.delete_model_by_column(
191-
db,
192-
logical_deletion=True,
193-
deleted_flag_column='is_deleted',
194-
allow_multiple=False,
195-
flush=True,
196-
id=item.id,
197-
)
213+
count = await crud_ins.delete_model_by_column(
214+
db,
215+
logical_deletion=True,
216+
deleted_flag_column='is_deleted',
217+
allow_multiple=False,
218+
flush=True,
219+
id=item.id,
220+
)
198221

199222
assert count == 1
200223

@@ -234,20 +257,23 @@ async def test_logical_delete_no_matching_records(db: AsyncSession, crud_ins: CR
234257

235258
@pytest.mark.asyncio
236259
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-
)
260+
first_count = await crud_ins.delete_model_by_column(
261+
db, logical_deletion=True, deleted_flag_column='is_deleted', allow_multiple=True, commit=True, id__le=3
262+
)
263+
assert first_count >= 0
241264

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-
)
265+
already_deleted_count = await crud_ins.count(db, id__le=3, is_deleted=True)
266+
assert already_deleted_count >= first_count
267+
268+
count = await crud_ins.delete_model_by_column(
269+
db,
270+
logical_deletion=True,
271+
deleted_flag_column='is_deleted',
272+
allow_multiple=True,
273+
commit=True,
274+
id__le=3,
275+
is_deleted=True,
276+
)
251277

252278
assert count >= 0
253279

@@ -295,23 +321,22 @@ async def test_logical_delete_single_but_multiple_found(
295321
async def test_logical_delete_affects_count(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
296322
initial_count = await crud_ins.count(db, is_deleted=False)
297323

324+
to_delete_count = await crud_ins.count(db, id__le=2, is_deleted=False)
325+
298326
deleted_count = await crud_ins.delete_model_by_column(
299327
db,
300328
logical_deletion=True,
301329
deleted_flag_column='is_deleted',
302330
allow_multiple=True,
303331
commit=True,
304332
id__le=2,
333+
is_deleted=False,
305334
)
306335

307336
final_count = await crud_ins.count(db, is_deleted=False)
308337

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

316341

317342
@pytest.mark.asyncio
@@ -359,7 +384,6 @@ async def test_logical_delete_with_select_models(db: AsyncSession, sample_ins: l
359384

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

365389
async with db.begin():
@@ -378,7 +402,6 @@ async def test_delete_model_by_column_with_deleted_at(db: AsyncSession, sample_i
378402
async def test_delete_model_by_column_without_deleted_at_column(
379403
db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]
380404
):
381-
# 使用数据库中存在的项目
382405
item = sample_ins[7]
383406

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

tests/test_filters.py

Lines changed: 23 additions & 10 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
@@ -156,22 +158,22 @@ async def test_filter_match(db: AsyncSession, sample_ins: list[Ins], crud_ins: C
156158
try:
157159
results = await crud_ins.select_models(db, name__match='item')
158160
assert len(results) >= 0
159-
except Exception:
160-
assert True
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
@@ -202,6 +204,13 @@ async def test_filter_mul(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRU
202204
assert len(results) >= 0
203205

204206

207+
@pytest.mark.asyncio
208+
async def test_filter_mul_with_condition(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
209+
results = await crud_ins.select_models(db, id__mul={'value': 2, 'condition': {'gt': 0}})
210+
211+
assert len(results) >= 0
212+
213+
205214
@pytest.mark.asyncio
206215
async def test_filter_rmul(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
207216
results = await crud_ins.select_models(db, id__rmul=3)
@@ -255,7 +264,9 @@ async def test_filter_rmod(db: AsyncSession, sample_ins: list[Ins], crud_ins: CR
255264
async def test_filter_or_same_field_list_values(db: AsyncSession, sample_ins: list[Ins], crud_ins: CRUDPlus[Ins]):
256265
results = await crud_ins.select_models(db, __or__={'is_deleted': [True, False]})
257266

258-
assert len(results) >= 0
267+
total_count = await crud_ins.count(db)
268+
assert len(results) == total_count
269+
assert all(r.is_deleted in [True, False] for r in results)
259270

260271

261272
@pytest.mark.asyncio
@@ -264,14 +275,16 @@ async def test_filter_or_different_fields_single_values(
264275
):
265276
results = await crud_ins.select_models(db, __or__={'is_deleted': True, 'id__gt': 5})
266277

267-
assert len(results) >= 0
278+
assert len(results) > 0
279+
assert all(r.is_deleted is True or r.id > 5 for r in results)
268280

269281

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

274-
assert len(results) >= 0
286+
assert len(results) > 0
287+
assert all('item_' in r.name or r.id < 3 for r in results)
275288

276289

277290
@pytest.mark.asyncio

0 commit comments

Comments
 (0)