Files
ai-customer-service/tech/TEST_QUALITY.md
Your Name cf46b27610 fix: P0-1 RateLimiter并发写安全 + P0-2工单操作错误码区分 + P1 rows.Close修复
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()
2026-05-01 20:56:25 +08:00

180 lines
7.5 KiB
Markdown
Raw Permalink 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.
# 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 严重盲区(必须修复)
1. **`cmd/ai-customer-service`0%**main.go 入口完全没有测试无法验证启动流程、flag 解析、环境变量加载。
2. **`internal/http`0%**HTTP 中间件、请求解析、响应序列化无测试。
3. **`internal/store/memory`0%**内存存储的并发安全RWMutex、容量限制、淘汰策略完全没有测试。
4. **`internal/store/postgres`1.6%**:真实数据库查询(会话存储、工单存储、知识库)完全没有覆盖。
5. **`internal/service/reply`5.7%**RAG 检索逻辑、回复生成降级、回复缓存等核心逻辑覆盖严重不足。
6. **`internal/app`20.7%**:应用层编排逻辑覆盖不足。
### 4.2 中等盲区
7. **`internal/platform/health`0%**:健康检查探针逻辑无测试。
8. **`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 - 阻断性问题
1. **为 `cmd/` 添加启动测试**:验证 main.go 在正常配置和错误配置下的行为。
2. **为 `internal/store/postgres` 添加 sqlmock 测试**:至少覆盖会话存储、工单创建/查询的 SQL 逻辑。
3. **为 `internal/store/memory` 添加并发安全测试**:验证 RWMutex 保护下的并发读写。
### P1 - 高优先级
4. **为 `internal/service/reply` 添加 RAG 检索测试**:模拟检索结果为空、低分、超长文本等场景。
5. **为 `internal/service/dialog` 补充边界测试**:当前只有 2 个测试,覆盖对话去重和工单生成,需要补充多轮对话上下文、转人工条件、敏感意图识别等场景。
6. **配置 E2E 测试矩阵到代码**:将 `TEST_DESIGN.md` 中的 TCS-*/TEC-* 用例编号映射到实际测试函数,便于追踪覆盖率。
### P2 - 建议改进
7. 为 integration 测试添加 `t.Parallel()`
8.`internal/http` 添加中间件测试(认证、签名校验、请求体限制)。
9. 补充 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*