样例:测试规范
下面是 CampusClaw 项目《测试规范 · CampusClaw》的原文,逐条列出,可直接照抄。
适用:
被谁读到:规则文件
backend/**/*_test.go、apitest/被谁读到:规则文件
.cursor/rules/testing.mdc,globs **/*_test.go;技能「按规范补测试」1. 层次与位置
| 层次 | 放哪里 | 覆盖什么 |
|---|---|---|
| 单元 | 被测包内 *_test.go | 业务规则:命中阈值、切分规则、作业状态流转 |
| 接口 | apitest/cases/<URL 路径>/<方法>.json | 每条能力的正常路径与失败路径 |
| 端到端 | apitest/cases/ 中标 e2e 的目录 | 只覆盖主路径:登录 → 检索 → 提问 → 看到出处 |
接口测试目录与 URL 对齐,文件名就是方法。例如 apitest/cases/api/v1/materials/GET.json。
2. 用例来源:每个测试说得出在判哪一条规约
测试名或注释里写清规约编号,例如:
materials_cross_class - R3.1 跨班与不存在返回一致的 404
submission_twice - R5.2 同一幂等键重复提交返回首次结果
说不出在判哪一条的测试,通常是顺手写的形状检查,删掉比留着好。
3. 三类组织(含边界)
每条能力按正常路径 / 失败路径 / 边界归组:
- 正常路径:本班检索命中并返回出处;
- 失败路径:跨班访问、未登录、依赖不可达(向量库停掉时
mode=hybrid返回 503); - 边界:空资料库、
SEARCH_VECTOR_MIN边界值附近、page_size取到上限。
边界用等价类划分的两端,不用随机值。
4. 不许只断言形状
这三句放在一起,把被测逻辑改坏它还是绿的:
assert.NoError(t, err)
assert.NotNil(t, rows)
assert.Len(t, rows, len(input))
要断言值:跨班访问的响应体与「不存在」的响应体逐字节相同;混合检索的结果里不含另一个班的标题。
判据:改坏被测逻辑,这个测试会不会红。 会红才算断言到了行为。
5. 数据隔离
- 测试用独立的库:
docker compose -f docker-compose.test.yml起一套,或用独立的 schema。 - 预置 A / B 两个班(含教师与学生各一名),每条用例运行前后自行清理;
- 随机化执行顺序后结果一致;跨班级的用例不依赖执行先后。
6. 外部依赖用替身
模型与向量库在单元测试中用替身;接口测试可以打真实服务,但要在只读数据上执行。禁止依赖真实时间与真实外部网络:断网后单元测试仍应全部通过。
7. 一键运行与通过判定
make check # go-vet go-build go-test fe-typecheck fmt-check complexity layout secret-scan ...
任一子项非零退出码即未通过。不得为了让门禁变绿而放宽其中的检查或删断言。
t.Skip 必须带理由与追踪编号;跳过用例数只许下降,不许增长。
8. 变更时的要求
每次变更至少补写与其场景对应的用例;修复缺陷先补一条能复现该缺陷的用例,再改代码,最后保留该用例。
违反时
失败即阻断。若认为某条断言本身写错了,改断言并在变更说明里写明原因,不由执行者自行跳过。