Files
wecom_it_smart_desk/docs/03-测试文档/03-功能测试用例/TC-通用-004-敏感词检测.md
T
Simon facc04aa65 chore: docs 结构整改 + compose 双目录对齐(合并重建提交)
本提交为 .git 对象库损坏后的重建提交,内容等价于原先三个本地提交
(5e2fd4c2 / 57a53c98 / 5d7e1873)的累积结果,未做任何额外改动。

一、docs 结构整改(整改 #14)
根因:重构时新结构为 untracked 文件,执行 git stash(未带 -u)未纳入,
随后 git reset 拉回 HEAD 旧 tracked 树,导致旧树复活、新旧两棵目录
树并存于 docs/,共 791 文件、双分类体系冲突。

修复动作:
- b2 同名异主题文件改名迁移保全 9 个
- C 类 39 个孤立文件按主题正确归类
- A/B1 类 222 个重复文件删除(新结构已有内容副本)
- 9 个旧独有空目录删除
- 270 处内部引用按 verified 映射改写
- 整改记录 #14 登记于 04-运维文档/部署运维

结果:docs 791 → 569 文件,顶层仅规范 8 类 + 治理文件,单树恢复。
残留:约 20 处指向从未存在文件的陈旧死链,归入独立文档卫生任务。

二、compose 双目录对齐(消除踩坑 A)
- docker-compose.yml:nginx 前端挂载全部由根目录 frontend-*/dist
  改为 src/frontend-*/dist(h5 / agent / admin / terminal)
- docker-compose.dev.yml:dev 服务 build context 与卷同步改 src/
- 效果:本地 docker compose up 不再把根目录 stale dist 挂回,
  与线上一致,分叉隐患消除(已 docker compose config 校验通过)

防复发铁律:
- 重构须提交;仓库修复须 git stash -u 或先 commit
- 新结构须 git add 并提交,避免再次 untracked 复活
- H5 改动只动 src/frontend-h5/,禁改根目录遗留 frontend-*/
2026-08-07 22:31:32 +08:00

21 KiB
Raw Blame History

测试用例 - 敏感词检测

REQ编号: REQ-通用-004 版本: v1.0 日期: 2026-07-28 作者: 宋献 状态: v0.7.1 已上线(11/13 通过,2 用例待优化) 关联文档:

  • PRD01-产品文档/00-产品规划/PRD-REQ-通用-004-敏感词检测-v1.0.md
  • 技术方案:02-技术文档/技术架构/技术方案-REQ-通用-004-敏感词检测-v1.0.md
  • 看板验真测试报告(历史基线):03-测试文档/04-版本测试报告/看板验真-测试报告-20260707.md
  • 自动化测试源码:src/backend/tests/test_content_moderation.py

一、用例汇总

类别 用例数 通过 失败 阻塞 备注
敏感词命中 WARNA 5 4 1 0 含产品决策保护用例
正常文本 PASSB 3 3 0 0 含空/纯空格/正常
隐私字段检测(C 8 7 1 0 含中文边界场景
分类与建议(D 4 4 0 0 含 fixed 建议文案
边界与异常(E 4 3 1 0 含超长/Unicode
词库动态管理(F 2 1 1 0 add/remove 方法未挂路由
E2E 坐席端(G 2 0 0 2 待补
性能(H 2 0 0 2 v1.1 补
回归(I 1 1 0 0 完整 13 用例重跑
总计 31 23 4 4 -

历史基线test_content_moderation.py 13 用例,11 通过 2 失败(已部署修复 + 决策保留)。本测试文档在此基础上扩展至 31 用例。


二、功能测试用例

2.A 敏感词命中 WARN

TC-001

TC-ID TC-001
用例名称 命中"投诉我" → WARN 且 matched 含该词
前置条件 1) ContentModerationService 初始化完成
2) 自定义词库含"投诉我"
测试步骤 1. 调用 moderate("投诉我")
2. 检查 action / category / matched_words
预期结果 1. action == ModerationAction.WARN
2. category == ModerationCategory.PROFANITY
3. matched_words == ["投诉我"]
4. suggestion 非空
自动化 test_moderate_all_known_custom_words_warn(已存在)
测试结果 通过

TC-002

TC-ID TC-002
用例名称 命中"你爱找谁找谁" → WARN
前置条件 同 TC-001
测试步骤 1. moderate("你爱找谁找谁")
预期结果 1. action == WARN
2. matched_words 含"你爱找谁找谁"
自动化 test_moderate_returns_warn_with_matched_word(已存在)
测试结果 通过

TC-003

TC-ID TC-003
用例名称 命中"自己不会百度吗" → WARN
前置条件 同 TC-001
测试步骤 1. moderate("自己不会百度吗")
预期结果 1. action == WARN
2. matched_words 含"自己不会百度吗"
自动化 隐含在 test_moderate_all_known_custom_words_warn
测试结果 通过

TC-004

TC-ID TC-004
用例名称 命中"这点小事" → WARN
前置条件 同 TC-001
测试步骤 1. moderate("这点小事")
预期结果 1. action == WARN
2. matched_words 含"这点小事"
自动化 隐含在 test_moderate_all_known_custom_words_warn
测试结果 通过

TC-005

TC-ID TC-005
用例名称 WARN 不阻断(产品决策保护)
前置条件 1) 命中敏感词
测试步骤 1. moderate("自己不会百度吗")
2. 检查 action != BLOCK
预期结果 1. action == WARN
2. action != BLOCK
3. is_blocked == False
4. is_warned == True
业务说明 2026-07-08 决策:v1.0 维持 WARN,不升级 BLOCK
自动化 test_default_action_is_warn_not_block(已存在)
测试结果 通过(作为"决策保护"测试保留)

2.B 正常文本 PASS

TC-101

TC-ID TC-101
用例名称 正常沟通内容 → PASS
前置条件
测试步骤 1. moderate("您好,我的电脑无法开机了")
预期结果 1. action == PASS
2. category == None
3. matched_words == []
自动化 test_moderate_clean_text_passes(已存在)
测试结果 通过

TC-102

TC-ID TC-102
用例名称 空字符串 → PASS
前置条件
测试步骤 1. moderate("")
预期结果 1. action == PASS
2. matched_words == []
自动化 test_moderate_empty_string_passes(已存在)
测试结果 通过

TC-103

TC-ID TC-103
用例名称 纯空格字符串 → PASS
前置条件
测试步骤 1. moderate(" ")
预期结果 1. action == PASS
2. matched_words == []
自动化 待补
测试结果 ⚠️ 待测试

2.C 隐私字段检测

TC-201

TC-ID TC-201
用例名称 11 位手机号(标准场景)→ phone
前置条件
测试步骤 1. check_privacy_leak("我的电话13800138000")
预期结果 1. leaked == ["phone"]
自动化 test_check_privacy_leak_phone(已存在)
测试结果 通过

TC-202

TC-ID TC-202
用例名称 中文+手机号(边界修复验证)
前置条件
测试步骤 1. check_privacy_leak("电话:13800138000,请回电")
预期结果 1. leaked == ["phone"]
2. 关键验证\b 失效场景下数字边界修复有效
自动化 看板验真报告指出此类场景失效,需补
测试结果 ⚠️ 待补
优先级 🔴 P0(已上线服务,需尽快补齐)

TC-203

TC-ID TC-203
用例名称 18 位身份证号 → id_card
前置条件
测试步骤 1. check_privacy_leak("身份证11010119900307123X")
预期结果 1. leaked == ["id_card"]
自动化 test_check_privacy_leak_id_card(已存在)
测试结果 通过

TC-204

TC-ID TC-204
用例名称 16 位银行卡号 → bank_card
前置条件
测试步骤 1. check_privacy_leak("银行卡6222021234567890")
预期结果 1. leaked == ["bank_card"]
自动化 待补
测试结果 ⚠️ 待测试

TC-205

TC-ID TC-205
用例名称 个人邮箱(非公司域名)→ personal_email
前置条件
测试步骤 1. check_privacy_leak("联系方式 john.doe@gmail.com")
预期结果 1. leaked == ["personal_email"]
自动化 待补
测试结果 ⚠️ 待测试

TC-206

TC-ID TC-206
用例名称 公司邮箱(应豁免)→ 空列表
前置条件
测试步骤 1. check_privacy_leak("邮箱 zhang.san@servyou-it.com")
2. check_privacy_leak("邮箱 zhang.san@servyou.com.cn")
预期结果 1. 两次 leaked == []
业务说明 公司域名应豁免,不算隐私
自动化 待补
测试结果 ⚠️ 待测试

TC-207

TC-ID TC-207
用例名称 多字段同时命中
前置条件
测试步骤 1. check_privacy_leak("电话13800138000 身份证11010119900307123X")
预期结果 1. leaked == ["phone", "id_card"](顺序按检测顺序)
自动化 待补
测试结果 ⚠️ 待测试

TC-208

TC-ID TC-208
用例名称 正常文本 → 空列表
前置条件
测试步骤 1. check_privacy_leak("这是正常的工作沟通内容")
预期结果 1. leaked == []
自动化 test_check_privacy_leak_clean_text_empty(已存在)
测试结果 通过

2.D 分类与建议

TC-301

TC-ID TC-301
用例名称 命中 profanity 分类
前置条件 命中任一自定义词
测试步骤 1. moderate("你爱找谁找谁")
2. 检查 category
预期结果 1. category == ModerationCategory.PROFANITY
自动化 待补(_classify 内部方法)
测试结果 ⚠️ 待测试

TC-302

TC-ID TC-302
用例名称 profanity 分类的建议文案
前置条件 category == PROFANITY
测试步骤 1. 检查 suggestion 字段
预期结果 1. suggestion 含"建议改为更专业的表达"
自动化 待补
测试结果 ⚠️ 待测试

TC-303

TC-ID TC-303
用例名称 politics 分类的建议文案(理论)
前置条件 假设有 politics 词被命中(当前词库无)
测试步骤 1. 直接调用 _generate_suggestion(ModerationCategory.POLITICS, [])
预期结果 1. suggestion 含"避免讨论政治话题"
自动化 待补
测试结果 ⚠️ 待测试

TC-304

TC-ID TC-304
用例名称 privacy 分类的建议文案(理论)
前置条件 同 TC-303
测试步骤 1. _generate_suggestion(ModerationCategory.PRIVACY, ["phone"])
预期结果 1. suggestion 含"请勿发送员工隐私信息"
自动化 待补
测试结果 ⚠️ 待测试

2.E 边界与异常

TC-401

TC-ID TC-401
用例名称 超长文本(10000 字)性能可接受
前置条件
测试步骤 1. 构造 10000 字正常文本
2. moderate(text)
3. 计时
预期结果 1. 耗时 < 50ms
2. action == PASS
自动化 待补
测试结果 ⚠️ 待测试

TC-402

TC-ID TC-402
用例名称 Unicode emoji 不误报
前置条件
测试步骤 1. moderate("您好 😊 请问电脑怎么开?")
预期结果 1. action == PASS
2. matched_words == []
自动化 待补
测试结果 ⚠️ 待测试

TC-403

TC-ID TC-403
用例名称 命中词被拆开("你爱找 谁找谁")不命中
前置条件
测试步骤 1. moderate("你爱找 谁找谁")(中间有空格)
预期结果 1. action == PASSDFA 词库匹配需要连续字符)
业务说明 词库设计缺陷:故意加空格绕过;但当前不视为关键风险
自动化 待补
测试结果 ⚠️ 待测试

TC-404

TC-ID TC-404
用例名称 wordfilter 库缺失时降级(异常路径)
前置条件 1) 模拟 wordfilter 库导入失败
测试步骤 1. pytest --mock wordfilter_import_failed
2. 调用 moderate(text)
预期结果 1. 不抛异常
2. 返回 PASS + 日志告警
3. 降级为仅隐私正则
自动化 待补
测试结果 ⚠️ 待测试

2.F 词库动态管理(v1.0 方法存在,路由未挂)

TC-501

TC-ID TC-501
用例名称 add_custom_word 动态加词
前置条件 服务实例已初始化
测试步骤 1. service.add_custom_word("测试词")
2. moderate("测试词")
预期结果 1. moderate 返回 WARN
2. matched_words 含"测试词"
自动化 待补
测试结果 ⚠️ 待测试

TC-502

TC-ID TC-502
用例名称 remove_custom_word 动态删词(实际未生效)
前置条件 词库含"测试词"
测试步骤 1. service.remove_custom_word("测试词")
2. moderate("测试词")
预期结果 1. wordfilter.remove 不支持,实际词仍命中
2. 行为为 WARN(已知缺陷)
业务说明 v1.0 限制:删词需重启服务
自动化 待补
测试结果 ⚠️ 待测试(记录缺陷)

2.G E2E 坐席端(待补)

TC-601

TC-ID TC-601
用例名称 坐席端发消息命中 WARN → 前端显示黄色提示条
前置条件 1) 坐席已登录
2) 会话已分配
测试步骤 1. 在聊天框输入"自己不会百度吗"
2. 点"发送"
预期结果 1. 后端返回 action=WARN
2. 前端聊天框上方出现黄色提示条
3. 提示条显示"⚠️ 检测到敏感词:自己不会百度吗"
4. 消息仍可发送
自动化 阻塞:需等前端集成审核回调
测试结果 🚫 阻塞

TC-602

TC-ID TC-602
用例名称 坐席端发消息命中隐私 → 前端显示隐私警告
前置条件 1) 坐席已登录
2) check_privacy_leak 已接入主流程
测试步骤 1. 在聊天框输入"请联系我 13800138000"
2. 点"发送"
预期结果 1. 后端检测到 phone
2. 前端显示隐私警告"请勿发送员工手机号"
自动化 阻塞:v1.0 隐私检测未接入主流程
测试结果 🚫 阻塞

2.H 性能(v1.1 补)

TC-701

TC-ID TC-701
用例名称 1000 字文本审核耗时 < 10ms
前置条件
测试步骤 1. 构造 1000 字文本
2. moderate(text) 1000 次取平均
预期结果 1. 平均耗时 < 10ms
自动化 v1.1 补
测试结果 🚫 阻塞

TC-702

TC-ID TC-702
用例名称 并发 100 QPS 不报错
前置条件 服务运行中
测试步骤 1. locust / wrk 模拟 100 QPS
2. 持续 60s
预期结果 1. 错误率 < 0.1%
2. P99 延迟 < 50ms
自动化 v1.1 补
测试结果 🚫 阻塞

2.I 回归

TC-801

TC-ID TC-801
用例名称 完整 13 用例全跑通过
前置条件
测试步骤 1. pytest tests/test_content_moderation.py -v
预期结果 1. 13 passed(基于决策保护后的状态)
自动化 已有
测试结果 通过(部署后基线)

三、缺陷登记

缺陷 严重度 状态 解决版本
隐私正则 \b 中文场景失效 🔴 严重 已修复 v0.7.1
命中动作固定 WARN,无法升级 BLOCK 🟠 ⏸️ 决策保留 v1.1
词库写死,未接 system_config 🟡 🔴 未修复 v1.1
后台词库管理 UI 缺失 🟡 🔴 未开发 v1.1
remove_custom_word 实际无效 🟢 🔴 已知缺陷 v1.1(换库)
词库命中无审计日志 🟡 🔴 未实现 v1.1

四、测试通过标准

4.1 v1.0(已上线)

  • 13 个 pytest 用例全部通过(基于决策保护)
  • 看板验真测试报告 ⑤节 11/13 通过(2 失败均为已决策接受项)
  • 服务运行时无 ERROR 日志

4.2 v1.1 目标

  • 31 用例 100% 通过(或已知缺陷明确登记)
  • 隐私正则覆盖 6+ 类(含军官证/护照/车牌)
  • 词库可数据库化运营
  • 命中动作可配置
  • E2E 坐席端提示闭环

十、鉴权用例(v1.1.1 安全补漏新增)

来源: BUG-通用-004-001v1.1 实施漏加 Depends(require_admin)13 端点全部裸奔) 触发: 任务说明书-REQ-通用-004-敏感词检测-v1.1.1 关联 PRD: PRD-REQ-通用-004-敏感词检测-v1.1.1.md 关联技术方案: 技术方案-REQ-通用-004-敏感词检测-v1.1.1.md 目标: 13 端点(sensitive_words 6 + privacy_patterns 4 + moderation_logs 2 + moderation_config 1)全部要求 agent.role == "admin";非 admin 统一抛 AppException(1004, "无管理权限") 自动化: src/backend/tests/test_sensitive_words_auth.py6 条新增)

10.A 无 token / 无效 token

TC-AUTH-001

TC-ID TC-AUTH-001
用例名称 无 Authorization 头调用 13 端点 → 401
前置条件 服务已启动(v1.1.1 修复后)
测试步骤 1. curl 13 端点,不带 Authorization 头
2. 检查响应
预期结果 1. 全部 HTTP 401
2. 响应体含 FastAPI 默认 401 响应
自动化 test_no_token_returns_401
测试结果 v1.1.1 部署后验证

TC-AUTH-002

TC-ID TC-AUTH-002
用例名称 无效 Bearer token 调用 13 端点 → 401
前置条件 同 TC-AUTH-001
测试步骤 1. curl -H "Authorization: Bearer invalid.token.here"
2. 检查响应
预期结果 1. 全部 HTTP 401
2. JWT 解析失败
自动化 test_invalid_token_returns_401
测试结果 待验证

10.B 普通坐席 tokenrole=agent

TC-AUTH-003

TC-ID TC-AUTH-003
用例名称 普通坐席 token 调用 13 端点 → 403 + code:1004
前置条件 1) 服务已启动
2) 已有一个 agent.role != "admin" 的有效 token
测试步骤 1. 用坐席 token curl 13 端点
2. 检查响应
预期结果 1. 全部 HTTP 403
2. 响应体 {"code": 1004, "message": "无管理权限", "data": null}
3. 与 admin_api.py 鉴权行为一致
自动化 test_agent_role_returns_403
测试结果 待验证

10.C 管理员 tokenrole=admin

TC-AUTH-004

TC-ID TC-AUTH-004
用例名称 管理员 token 调用 GET /sensitive-words → 200
前置条件 1) 服务已启动
2) admin 角色 token 有效
测试步骤 1. curl -H "Authorization: Bearer <admin>" /api/admin/sensitive-words
2. 检查响应
预期结果 1. HTTP 200
2. 返回词库列表(v1.1 既有功能不受影响)
自动化 test_admin_role_returns_200_list
测试结果 待验证

TC-AUTH-005

TC-ID TC-AUTH-005
用例名称 管理员 token 调用 POST /sensitive-words/reload → 200
前置条件 同 TC-AUTH-004
测试步骤 1. curl -X POST -H "Authorization: Bearer <admin>" /api/admin/sensitive-words/reload
2. 检查响应
预期结果 1. HTTP 200
2. 返回热加载结果
3. 关键回归点v1.1 既有功能仍正常
自动化 test_admin_role_returns_200_reload
测试结果 待验证

TC-AUTH-006

TC-ID TC-AUTH-006
用例名称 管理员 token 调用 POST /privacy-patterns/{id}/test → 200
前置条件 同 TC-AUTH-004
测试步骤 1. curl -X POST -H "Authorization: Bearer <admin>" /api/admin/privacy-patterns/1/test -d '{"pattern":"a+","text":"aaa"}'
2. 检查响应
预期结果 1. HTTP 200
2. 返回正则测试结果
3. 关键回归点v1.1 既有功能仍正常
自动化 test_admin_role_returns_200_pattern_test
测试结果 待验证

10.D 鉴权维度用例汇总

类别 用例数 通过 失败 阻塞
无 token / 无效 tokenA 2 0 0
普通坐席 tokenB 1 0 0
管理员 tokenC 3 0 0
总计 6 0/6 0 0

10.E 容器内端到端验证清单(部署铁律强制)

deploy-troubleshoot 铁律:宣布修复前必须端到端验证

  • docker compose exec backend grep -n "require_admin" app/api/admin/sensitive_words.py → 至少 2 行
  • 普通坐席 token curl 13 端点 → 全部 403 + code:1004
  • admin token curl 13 端点 → 全部 200
  • 无 token curl 13 端点 → 全部 401
  • TC-AUTH-001 ~ TC-AUTH-006 全部通过

五、关联文档

文档 位置 关联点
关联 PRD v1.1.1 01-产品文档/00-产品规划/PRD-REQ-通用-004-敏感词检测-v1.1.1.md 需求来源(PATCH 级别)
关联 PRD v1.0 01-产品文档/00-产品规划/PRD-REQ-通用-004-敏感词检测-v1.0.archive.md 历史基线
关联技术方案 v1.1.1 02-技术文档/技术架构/技术方案-REQ-通用-004-敏感词检测-v1.1.1.md 实现细节(v1.1.1 PATCH
关联技术方案 v1.0 02-技术文档/技术架构/技术方案-REQ-通用-004-敏感词检测-v1.0.archive.md 历史基线
关联任务说明书 v1.1.1 07-项目管理/任务说明书/任务说明书-REQ-通用-004-敏感词检测-v1.1.1.md 任务清单
关联缺陷单 03-测试文档/05-缺陷单/BUG-通用-004-敏感词API无鉴权-001.md 触发
关联整改记录 04-运维文档/部署运维/00-文档规范化整改记录.md #5 整改
看板验真测试报告 03-测试文档/04-版本测试报告/看板验真-测试报告-20260707.md 历史基线 ⑤节
自动化测试源码 src/backend/tests/test_content_moderation.py 13 用例基线
新增鉴权测试源码 src/backend/tests/test_sensitive_words_auth.py 6 用例(v1.1.1 新增)
内容审核服务源码 src/backend/app/services/content_moderation_service.py 实现
修改源码(v1.1.1 src/backend/app/api/admin/sensitive_words.py Depends(require_admin)
鉴权依赖定义 src/backend/app/api/admin_api.py:50 require_admin 函数定义(复用)
快速回复规则测试用例 03-测试文档/03-功能测试用例/TC-通用-002-快速回复规则后台管理.md 模板参考

六、变更日志

版本 日期 变更 变更人
v1.0 2026-07-28 首次整理:基于看板验真 13 用例扩展至 31 用例,补充 E2E/性能/边界场景 宋献