test(base): 基础数据管理模块集成用例(48 例)与审计盲区修复
- 覆盖:401/引用校验/删除保护/子表全量替换/类别与组合唯一/归属变更留痕/审计双记录 - 缺陷修复:personnel/product/customer 三 service 的前置校验移入审计上下文, 校验失败(400)同样留痕(成功与失败都记的既定原则) - conftest 兜底清理扩展到 M2 五表(留痕无外键,按 operator_name + 前缀双轨清理) Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
15de81dd2c
commit
ca88ee7a0b
12 files changed
+1090
-29
No files matched your search
@@ -7,6 +7,9 @@
|
||||
- 测试账号/角色统一 ``t_`` 前缀;工厂夹具清理自己创建的对象,另有
|
||||
autouse 兜底按前缀全量清理(用例经**接口**创建的数据不在工厂名下,
|
||||
失败中断时会残留并影响后续用例的 total 断言)
|
||||
- M2 基础数据(人员姓名/产品名/公司名/测试岗位编码)同用 ``t_`` 前缀,
|
||||
兜底清理按前缀删除;归属留痕对客户/人员 ID 无外键固化、不随主表删除
|
||||
消失,必须显式清理,否则残留会影响后续用例对留痕条数的断言
|
||||
- 操作日志的清理同时按 username 与 user_id —— 账号被删除后其 ``user_id``
|
||||
会被 SET NULL,只能靠冗余的 username 追溯,清理逻辑必须覆盖两种状态
|
||||
"""
|
||||
@@ -14,12 +17,24 @@
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import delete, select
|
||||
from sqlalchemy import delete, select, update
|
||||
|
||||
from app.core.constants import ROLE_ADMIN, ROLE_USER
|
||||
from app.core.db import get_session_factory
|
||||
from app.core.security import create_access_token, hash_password
|
||||
from app.models import OperationLog, Role, User, UserRole
|
||||
from app.models import (
|
||||
BusinessRole,
|
||||
Customer,
|
||||
OperationLog,
|
||||
OwnershipChangeLog,
|
||||
Personnel,
|
||||
PersonnelPlan,
|
||||
PersonnelRegion,
|
||||
Product,
|
||||
Role,
|
||||
User,
|
||||
UserRole,
|
||||
)
|
||||
|
||||
TEST_PASSWORD = "TestPwd@2026"
|
||||
# 模块级预计算一次:bcrypt(rounds=12)单次约 0.2–0.4 秒,逐用例重复哈希
|
||||
@@ -53,6 +68,45 @@ def _purge_test_data() -> None:
|
||||
if role_ids:
|
||||
session.execute(delete(UserRole).where(UserRole.role_id.in_(role_ids)))
|
||||
session.execute(delete(Role).where(Role.id.in_(role_ids)))
|
||||
|
||||
# ---- M2 基础数据:客户/归属留痕/人员/产品/测试岗位 ----
|
||||
# 外键均为 RESTRICT,删除顺序不能倒:留痕无外键先按 customer_id 清,
|
||||
# 再删客户(子表)→ 人员(先置空 manager_id 自引用、清子表)→ 产品
|
||||
personnel_ids = list(
|
||||
session.execute(
|
||||
select(Personnel.id).where(Personnel.personnel_name.like("t\\_%"))
|
||||
).scalars()
|
||||
)
|
||||
customer_ids = list(
|
||||
session.execute(
|
||||
select(Customer.id).where(Customer.company_name.like("t\\_%"))
|
||||
).scalars()
|
||||
)
|
||||
if customer_ids:
|
||||
session.execute(
|
||||
delete(OwnershipChangeLog).where(OwnershipChangeLog.customer_id.in_(customer_ids))
|
||||
)
|
||||
session.execute(delete(Customer).where(Customer.id.in_(customer_ids)))
|
||||
# 客户被物理删除后其 customer_id 已无从收集,按操作人用户名兜底一条
|
||||
session.execute(
|
||||
delete(OwnershipChangeLog).where(OwnershipChangeLog.operator_name.like("t\\_%"))
|
||||
)
|
||||
if personnel_ids:
|
||||
session.execute(
|
||||
update(Personnel)
|
||||
.where(Personnel.manager_id.in_(personnel_ids))
|
||||
.values(manager_id=None)
|
||||
)
|
||||
session.execute(
|
||||
delete(PersonnelRegion).where(PersonnelRegion.personnel_id.in_(personnel_ids))
|
||||
)
|
||||
session.execute(
|
||||
delete(PersonnelPlan).where(PersonnelPlan.personnel_id.in_(personnel_ids))
|
||||
)
|
||||
session.execute(delete(Personnel).where(Personnel.id.in_(personnel_ids)))
|
||||
session.execute(delete(Product).where(Product.product_name.like("t\\_%")))
|
||||
# 人员已先删(business_role_id 外键 RESTRICT),直建的测试岗位此时可安全删
|
||||
session.execute(delete(BusinessRole).where(BusinessRole.role_code.like("t\\_%")))
|
||||
session.commit()
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user