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

578 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 测试用例 - 敏感词检测
> **REQ编号**: REQ-通用-004
> **版本**: v1.0
> **日期**: 2026-07-28
> **作者**: 宋献
> **状态**: v0.7.1 已上线(11/13 通过,2 用例待优化)
> **关联文档**:
> - PRD`01-产品文档/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 初始化完成<br>2) 自定义词库含"投诉我" |
| 测试步骤 | 1. 调用 `moderate("投诉我")`<br>2. 检查 action / category / matched_words |
| 预期结果 | 1. action == `ModerationAction.WARN`<br>2. category == `ModerationCategory.PROFANITY`<br>3. matched_words == `["投诉我"]`<br>4. suggestion 非空 |
| 自动化 | ✅ `test_moderate_all_known_custom_words_warn`(已存在) |
| 测试结果 | ✅ 通过 |
#### TC-002
| TC-ID | TC-002 |
|-------|--------|
| 用例名称 | 命中"你爱找谁找谁" → WARN |
| 前置条件 | 同 TC-001 |
| 测试步骤 | 1. `moderate("你爱找谁找谁")` |
| 预期结果 | 1. action == WARN<br>2. matched_words 含"你爱找谁找谁" |
| 自动化 | ✅ `test_moderate_returns_warn_with_matched_word`(已存在) |
| 测试结果 | ✅ 通过 |
#### TC-003
| TC-ID | TC-003 |
|-------|--------|
| 用例名称 | 命中"自己不会百度吗" → WARN |
| 前置条件 | 同 TC-001 |
| 测试步骤 | 1. `moderate("自己不会百度吗")` |
| 预期结果 | 1. action == WARN<br>2. matched_words 含"自己不会百度吗" |
| 自动化 | ✅ 隐含在 `test_moderate_all_known_custom_words_warn` |
| 测试结果 | ✅ 通过 |
#### TC-004
| TC-ID | TC-004 |
|-------|--------|
| 用例名称 | 命中"这点小事" → WARN |
| 前置条件 | 同 TC-001 |
| 测试步骤 | 1. `moderate("这点小事")` |
| 预期结果 | 1. action == WARN<br>2. matched_words 含"这点小事" |
| 自动化 | ✅ 隐含在 `test_moderate_all_known_custom_words_warn` |
| 测试结果 | ✅ 通过 |
#### TC-005
| TC-ID | TC-005 |
|-------|--------|
| 用例名称 | **WARN 不阻断(产品决策保护)** |
| 前置条件 | 1) 命中敏感词 |
| 测试步骤 | 1. `moderate("自己不会百度吗")`<br>2. 检查 action != BLOCK |
| 预期结果 | 1. action == WARN<br>2. action != BLOCK<br>3. is_blocked == False<br>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<br>2. category == None<br>3. matched_words == [] |
| 自动化 | ✅ `test_moderate_clean_text_passes`(已存在) |
| 测试结果 | ✅ 通过 |
#### TC-102
| TC-ID | TC-102 |
|-------|--------|
| 用例名称 | 空字符串 → PASS |
| 前置条件 | 无 |
| 测试步骤 | 1. `moderate("")` |
| 预期结果 | 1. action == PASS<br>2. matched_words == [] |
| 自动化 | ✅ `test_moderate_empty_string_passes`(已存在) |
| 测试结果 | ✅ 通过 |
#### TC-103
| TC-ID | TC-103 |
|-------|--------|
| 用例名称 | 纯空格字符串 → PASS |
| 前置条件 | 无 |
| 测试步骤 | 1. `moderate(" ")` |
| 预期结果 | 1. action == PASS<br>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"]`<br>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")`<br>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("你爱找谁找谁")`<br>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 字正常文本<br>2. `moderate(text)`<br>3. 计时 |
| 预期结果 | 1. 耗时 < 50ms<br>2. action == PASS |
| 自动化 | ❌ 待补 |
| 测试结果 | ⚠️ 待测试 |
#### TC-402
| TC-ID | TC-402 |
|-------|--------|
| 用例名称 | Unicode emoji 不误报 |
| 前置条件 | 无 |
| 测试步骤 | 1. `moderate("您好 😊 请问电脑怎么开?")` |
| 预期结果 | 1. action == PASS<br>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`<br>2. 调用 `moderate(text)` |
| 预期结果 | 1. 不抛异常<br>2. 返回 PASS + 日志告警<br>3. 降级为仅隐私正则 |
| 自动化 | ❌ 待补 |
| 测试结果 | ⚠️ 待测试 |
---
### 2.F 词库动态管理(v1.0 方法存在,路由未挂)
#### TC-501
| TC-ID | TC-501 |
|-------|--------|
| 用例名称 | add_custom_word 动态加词 |
| 前置条件 | 服务实例已初始化 |
| 测试步骤 | 1. `service.add_custom_word("测试词")`<br>2. `moderate("测试词")` |
| 预期结果 | 1. moderate 返回 WARN<br>2. matched_words 含"测试词" |
| 自动化 | ❌ 待补 |
| 测试结果 | ⚠️ 待测试 |
#### TC-502
| TC-ID | TC-502 |
|-------|--------|
| 用例名称 | remove_custom_word 动态删词(实际未生效) |
| 前置条件 | 词库含"测试词" |
| 测试步骤 | 1. `service.remove_custom_word("测试词")`<br>2. `moderate("测试词")` |
| 预期结果 | 1. wordfilter.remove 不支持,实际词仍命中<br>2. 行为为 WARN(已知缺陷) |
| 业务说明 | v1.0 限制:删词需重启服务 |
| 自动化 | ❌ 待补 |
| 测试结果 | ⚠️ 待测试(记录缺陷) |
---
### 2.G E2E 坐席端(待补)
#### TC-601
| TC-ID | TC-601 |
|-------|--------|
| 用例名称 | 坐席端发消息命中 WARN → 前端显示黄色提示条 |
| 前置条件 | 1) 坐席已登录<br>2) 会话已分配 |
| 测试步骤 | 1. 在聊天框输入"自己不会百度吗"<br>2. 点"发送" |
| 预期结果 | 1. 后端返回 action=WARN<br>2. 前端聊天框上方出现黄色提示条<br>3. 提示条显示"⚠️ 检测到敏感词:自己不会百度吗"<br>4. 消息仍可发送 |
| 自动化 | ❌ 阻塞:需等前端集成审核回调 |
| 测试结果 | 🚫 阻塞 |
#### TC-602
| TC-ID | TC-602 |
|-------|--------|
| 用例名称 | 坐席端发消息命中隐私 → 前端显示隐私警告 |
| 前置条件 | 1) 坐席已登录<br>2) `check_privacy_leak` 已接入主流程 |
| 测试步骤 | 1. 在聊天框输入"请联系我 13800138000"<br>2. 点"发送" |
| 预期结果 | 1. 后端检测到 phone<br>2. 前端显示隐私警告"请勿发送员工手机号" |
| 自动化 | ❌ 阻塞:v1.0 隐私检测未接入主流程 |
| 测试结果 | 🚫 阻塞 |
---
### 2.H 性能(v1.1 补)
#### TC-701
| TC-ID | TC-701 |
|-------|--------|
| 用例名称 | 1000 字文本审核耗时 < 10ms |
| 前置条件 | 无 |
| 测试步骤 | 1. 构造 1000 字文本<br>2. `moderate(text)` 1000 次取平均 |
| 预期结果 | 1. 平均耗时 < 10ms |
| 自动化 | ❌ v1.1 补 |
| 测试结果 | 🚫 阻塞 |
#### TC-702
| TC-ID | TC-702 |
|-------|--------|
| 用例名称 | 并发 100 QPS 不报错 |
| 前置条件 | 服务运行中 |
| 测试步骤 | 1. locust / wrk 模拟 100 QPS<br>2. 持续 60s |
| 预期结果 | 1. 错误率 < 0.1%<br>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(已上线)
- [x] 13 个 pytest 用例全部通过(基于决策保护)
- [x] 看板验真测试报告 ⑤节 11/13 通过(2 失败均为已决策接受项)
- [x] 服务运行时无 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.py`6 条新增)
### 10.A 无 token / 无效 token
#### TC-AUTH-001
| TC-ID | TC-AUTH-001 |
|-------|--------|
| 用例名称 | 无 Authorization 头调用 13 端点 → 401 |
| 前置条件 | 服务已启动(v1.1.1 修复后) |
| 测试步骤 | 1. curl 13 端点,不带 Authorization 头<br>2. 检查响应 |
| 预期结果 | 1. 全部 HTTP 401<br>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"`<br>2. 检查响应 |
| 预期结果 | 1. 全部 HTTP 401<br>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) 服务已启动<br>2) 已有一个 `agent.role != "admin"` 的有效 token |
| 测试步骤 | 1. 用坐席 token curl 13 端点<br>2. 检查响应 |
| 预期结果 | 1. 全部 HTTP 403<br>2. 响应体 `{"code": 1004, "message": "无管理权限", "data": null}`<br>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) 服务已启动<br>2) admin 角色 token 有效 |
| 测试步骤 | 1. `curl -H "Authorization: Bearer <admin>" /api/admin/sensitive-words`<br>2. 检查响应 |
| 预期结果 | 1. HTTP 200<br>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`<br>2. 检查响应 |
| 预期结果 | 1. HTTP 200<br>2. 返回热加载结果<br>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"}'`<br>2. 检查响应 |
| 预期结果 | 1. HTTP 200<br>2. 返回正则测试结果<br>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/性能/边界场景 | 宋献 |