P0-1 (limits.go): Allow()方法改为全程使用写锁保护counters map读写,避免RLock写入时的data race P0-2 (ticket_workflow.go+ticket_handler.go): Assign/Resolve/Close操作先查询ticket存在性和状态,返回明确的CS_TICKET_4001/CS_TKT_4002/CS_TICKET_4092/CS_TICKET_4093错误码,handler根据错误前缀路由HTTP状态码 P1-1 (ticket_store.go): 移除GetStats中3处手动rows.Close(),只保留defer Close()
7.5 KiB
7.5 KiB
TEST_QUALITY.md - 测试质量评估报告
版本:v1.0 日期:2026-04-30 审查者:TechLead v8 状态:初稿
1. 覆盖率概览
| Package | 覆盖率 | 状态 |
|---|---|---|
cmd/ai-customer-service |
0.0% | 🔴 严重 |
internal/http |
0.0% | 🔴 严重 |
internal/platform/health |
0.0% | 🔴 严重 |
internal/platform/logging |
0.0% | 🔴 严重 |
internal/store/memory |
0.0% | 🔴 严重 |
internal/store/postgres |
1.6% | 🔴 严重 |
internal/service/reply |
5.7% | 🔴 严重 |
internal/app |
20.7% | 🟡 低 |
internal/service/dialog |
48.7% | 🟡 低 |
test/e2e |
48.3% | 🟡 低 |
test/integration |
54.3% | 🟡 中 |
internal/service/intent |
80.8% | 🟢 达标 |
internal/platform/httpx |
84.3% | 🟢 达标 |
internal/config |
73.5% | 🟢 达标 |
internal/http/handlers |
72.1% | 🟢 达标 |
internal/service/handoff |
100.0% | 🟢 达标 |
internal/domain/error/cserrors |
100.0% | 🟢 达标 |
达标门槛:service/handler ≥ 80%, domain ≥ 70%(按 TEST_DESIGN.md)
结论:8/17 个包覆盖率 0% 或极低,主入口 cmd/ 和 HTTP 层完全无测试。
2. 边界条件测试覆盖
2.1 Content 截断边界(1999/2000/2001 字)
| 测试 | 状态 |
|---|---|
| 1999 字(< limit) | ✅ TestWebhook_ContentBoundary_1999Chars |
| 2000 字(= limit) | ✅ TestWebhook_ContentBoundary_2000Chars |
| 2001 字(> limit,截断) | ✅ TestWebhook_ContentBoundary_2001Chars |
| 截断触发审计事件 | ✅ TestWebhook_ContentBoundary_AuditOnTruncation |
评估:✅ 完全覆盖,包括截断行为和审计触发。
2.2 置信度阈值边界(0.59/0.60/0.61)
| 测试 | 状态 |
|---|---|
| confidence = 0.59(< 0.60)→ handoff P2 | ✅ TestShouldHandoff_ConfidenceBoundary |
| confidence = 0.60(= 0.60)→ no handoff | ✅ TestShouldHandoff_ConfidenceBoundary |
| confidence = 0.61(> 0.60)→ no handoff | ✅ TestShouldHandoff_ConfidenceBoundary |
评估:✅ 完全覆盖,在 internal/service/handoff/service_test.go 中覆盖了 turnCount=5 和 turnCount=4 的组合场景。
2.3 Rate Limit 边界(10/11 请求)
| 测试 | 状态 |
|---|---|
| 5 请求(< 10)全部通过 | ✅ TestWebhookRateLimit_WithinLimit |
| 10 请求(= limit)全部通过 | ✅ TestWebhookRateLimit_ExceedLimit 中前 10 个 |
| 11 请求(> 10)返回 429 | ✅ TestWebhookRateLimit_ExceedLimit |
| 不同 IP 独立计数 | ✅ TestWebhookRateLimit_DifferentIPs |
评估:✅ 完全覆盖,包括 IP 隔离和窗口重置。
2.4 空字符串与超长字符串
| 测试 | 状态 |
|---|---|
空 body {} → 400 |
✅ TestWebhook_EmptyBody |
仅有空白字符字段 " " → 400 |
✅ TestWebhook_WhitespaceOnlyFields |
| 缺失必需字段 → 400 | ✅ TestWebhook_MissingChannel/OpenID/Content |
| 超长内容(>2000字截断) | ✅ TestWebhook_ContentBoundary_* |
| 超长内容(2500字)审计触发 | ✅ TestWebhook_ContentBoundary_AuditOnTruncation |
评估:✅ 覆盖充分,边界和异常路径均有验证。
3. 测试隔离审查
3.1 外部状态依赖
内存存储(memory store):所有 handler 和 service 测试使用 memory.New*Store(),每个测试函数创建独立实例,无共享状态。
审查结果:✅ 无外部状态依赖,隔离良好。
3.2 Postgres 测试隔离
| 问题 | 现状 |
|---|---|
migrate_test.go 是否使用真实 DB? |
❌ 否,仅测试目录不存在的错误路径 |
是否有 sqlmock 配置? |
❌ 未发现 |
| 是否有事务回滚机制? | ❌ 未发现 |
store/postgres 包覆盖率 |
🔴 1.6%(仅 1 个错误路径测试) |
问题:internal/store/postgres 的真实查询逻辑(CRUD)完全没有测试覆盖。没有使用 sqlmock 模拟数据库响应。
建议:为 store/postgres 添加 sqlmock 测试,验证 SQL 查询、参数绑定和错误处理。
3.3 测试并行性
test/integration/ 和 handler 测试均使用 t.Run 子测试,但未发现 t.Parallel() 调用。在测试用例较少时这不是问题,但随着测试数量增长,并行化可以显著缩短 CI 时间。
4. 覆盖率盲区分析
4.1 严重盲区(必须修复)
cmd/ai-customer-service(0%):main.go 入口完全没有测试,无法验证启动流程、flag 解析、环境变量加载。internal/http(0%):HTTP 中间件、请求解析、响应序列化无测试。internal/store/memory(0%):内存存储的并发安全(RWMutex)、容量限制、淘汰策略完全没有测试。internal/store/postgres(1.6%):真实数据库查询(会话存储、工单存储、知识库)完全没有覆盖。internal/service/reply(5.7%):RAG 检索逻辑、回复生成降级、回复缓存等核心逻辑覆盖严重不足。internal/app(20.7%):应用层编排逻辑覆盖不足。
4.2 中等盲区
internal/platform/health(0%):健康检查探针逻辑无测试。internal/platform/logging(0%):日志结构化输出、level 过滤无测试。
5. 测试设计符合度
对照 TEST_DESIGN.md:
| 要求 | 实际 | 状态 |
|---|---|---|
| domain ≥ 70% | cserrors 100% ✅,ticket/session [no statements] ⚠️ |
🟡 |
| service/handler ≥ 80% | handoff 100% ✅,intent 80.8% ✅,httpx 84.3% ✅,handlers 72.1% 🟡,dialog 48.7% 🔴,reply 5.7% 🔴 | 🟡 |
| AC-01~AC-13 全部有测试 | 部分覆盖,未见完整对应矩阵 | 🟡 |
| EC-01~EC-10 全部有验证 | TEC-01/02/03 有覆盖,EC-04~EC-10 未见具体测试 | 🟡 |
| sqlmock 用于 PostgreSQL | ❌ 未配置 | 🔴 |
6. 改进建议(按优先级)
P0 - 阻断性问题
- 为
cmd/添加启动测试:验证 main.go 在正常配置和错误配置下的行为。 - 为
internal/store/postgres添加 sqlmock 测试:至少覆盖会话存储、工单创建/查询的 SQL 逻辑。 - 为
internal/store/memory添加并发安全测试:验证 RWMutex 保护下的并发读写。
P1 - 高优先级
- 为
internal/service/reply添加 RAG 检索测试:模拟检索结果为空、低分、超长文本等场景。 - 为
internal/service/dialog补充边界测试:当前只有 2 个测试,覆盖对话去重和工单生成,需要补充多轮对话上下文、转人工条件、敏感意图识别等场景。 - 配置 E2E 测试矩阵到代码:将
TEST_DESIGN.md中的 TCS-/TEC- 用例编号映射到实际测试函数,便于追踪覆盖率。
P2 - 建议改进
- 为 integration 测试添加
t.Parallel()。 - 为
internal/http添加中间件测试(认证、签名校验、请求体限制)。 - 补充 EC-04~EC-10 的可执行测试用例。
7. 质量评分
| 维度 | 评分 | 说明 |
|---|---|---|
| 边界条件覆盖 | 9/10 | 1999/2000/2001、0.59/0.60/0.61、10/11 全部覆盖,空串/超长覆盖良好 |
| 测试隔离 | 7/10 | memory store 隔离好;postgres 无真实 DB 测试,无 sqlmock |
| 覆盖率 | 4/10 | 8 个包 0%,主链路 cmd/http/store 严重缺失 |
| 边界用例设计 | 6/10 | 已有边界测试,但 AC/EC 测试矩阵未完整代码化 |
| 综合 | 6.5/10 | 基础扎实,盲区严重,需重点补齐 cmd/postgres/memory store |
审查时间:2026-04-30 22:22 GMT+8 | 审查工具:go test -cover