37a67f5810
- 在 Api 结构中新增 lastResp 字段以存储最近请求的响应 - 添加 Verify 方法,支持自定义校验函数并返回 ApiCase 构建器 - 新增 Resp 方法,获取最近一次请求的响应以便于断言 - 在 TestCollector 中添加 Visited 字段,记录已调用的路径 - 更新 GenerateSwagger 方法,支持部分运行时保留未运行端点的已有数据 - 完善文档,增加用例编写范式和示例,提升测试框架的可用性与易用性
146 lines
6.2 KiB
Markdown
146 lines
6.2 KiB
Markdown
---
|
||
name: 重写API测试框架文档
|
||
overview: 重新编撰 Testing_API测试框架.md,以"错误用例先行 → 准备数据 → 正确请求(含响应断言+DB校验)"的完整流程为核心范式,让文档成为可直接照搬的编写指南。
|
||
todos:
|
||
- id: rewrite-doc
|
||
content: 重写 docs/Testing_API测试框架.md:错误用例先行 → 模拟数据准备 → 正确请求(响应断言必须+DB校验) → 逐步讲解各环节 → API速查表 → 其余章节微调
|
||
status: completed
|
||
isProject: false
|
||
---
|
||
|
||
# 重写 API 测试框架文档
|
||
|
||
## 用户确认的编写规范
|
||
|
||
1. **顺序**:先写错误请求用例,再写正确请求用例
|
||
2. **错误用例**:三个参数必须填满 `Post("描述", status, "具体错误消息")`,因为错误码是复用的(如 status=3 可能对应多种参数校验错误)
|
||
3. **正确请求前**:用 `a.DB()` 模拟插入数据,既准备测试依赖数据,也可作为后续 DB 校验的对照
|
||
4. **响应字段断言**:正确响应情况下**必须**断言(至少覆盖重要字段),不能只写 `Post("描述", 0)`
|
||
5. **数据库校验**:只要接口改变了数据库状态,都**建议**用 Verify 校验结果
|
||
|
||
## 标准用例编写流程(范式)
|
||
|
||
```
|
||
错误用例(参数校验、权限校验等)
|
||
↓
|
||
准备测试数据(a.DB().Insert/Update 模拟前置数据)
|
||
↓
|
||
正确请求 + 响应结构校验(ExpectResult / 第三参数 Map)
|
||
↓
|
||
响应字段断言(resp.GetBody() 检查关键业务字段)
|
||
↓
|
||
数据库状态校验(Verify 查库确认写入/更新结果)
|
||
```
|
||
|
||
## 核心范例(贯穿文档的"创建订单"示例)
|
||
|
||
以下为快速开始中使用的完整范例,展示从业务代码到测试用例的映射:
|
||
|
||
```go
|
||
// order_test.go
|
||
var OrderTest = CtrTest{
|
||
"create": {Desc: "创建订单", Func: func(a *Api) {
|
||
// ======== 第一步:错误用例 ========
|
||
// 错误码复用,三个参数都必须填满
|
||
a.JSON(Map{"goods_id": int64(1), "quantity": 3, "address": "XX路1号"}).
|
||
Post("未登录创建订单", 2, "请先登录")
|
||
a.WithSession(Map{"user_id": int64(1)}).
|
||
JSON(Map{"quantity": 3, "address": "XX路1号"}).
|
||
Post("缺少商品ID", 3, "请选择商品")
|
||
a.WithSession(Map{"user_id": int64(1)}).
|
||
JSON(Map{"goods_id": int64(1), "address": "XX路1号"}).
|
||
Post("缺少数量", 3, "请填写购买数量")
|
||
a.WithSession(Map{"user_id": int64(1)}).
|
||
JSON(Map{"goods_id": int64(999), "quantity": 3, "address": "XX路1号"}).
|
||
Post("商品不存在", 4, "商品不存在")
|
||
|
||
// ======== 第二步:准备测试数据 ========
|
||
// 插入一条商品数据,后面的正确请求会依赖它
|
||
goodsId := a.DB().Insert("goods", Map{
|
||
"name": "测试商品", "price": 29.9, "stock": 100, "state": 1,
|
||
})
|
||
|
||
// ======== 第三步:正确请求 + 响应断言 + DB校验 ========
|
||
resp := a.WithSession(Map{"user_id": int64(1)}).
|
||
JSON(Map{"goods_id": goodsId, "quantity": 3, "address": "XX路1号"}).
|
||
Verify(func(a *Api) error {
|
||
row := a.DB().Get("order", "*", Map{"AND": Map{
|
||
"user_id": int64(1), "goods_id": goodsId,
|
||
}})
|
||
if row == nil {
|
||
return fmt.Errorf("order 表未写入订单记录")
|
||
}
|
||
if row.GetCeilInt64("state") != 0 {
|
||
return fmt.Errorf("新订单 state 期望 0, 实际 %d", row.GetCeilInt64("state"))
|
||
}
|
||
if row.GetCeilFloat64("total_price") != 29.9*3 {
|
||
return fmt.Errorf("total_price 期望 %.2f, 实际 %.2f", 29.9*3, row.GetCeilFloat64("total_price"))
|
||
}
|
||
// 校验库存扣减
|
||
goods := a.DB().Get("goods", "stock", Map{"id": goodsId})
|
||
if goods.GetCeilInt64("stock") != 97 {
|
||
return fmt.Errorf("库存期望 97, 实际 %d", goods.GetCeilInt64("stock"))
|
||
}
|
||
return nil
|
||
}).
|
||
Post("正常创建订单", 0, Map{
|
||
"id": int64(1), "sn": "sample", "total_price": float64(1.0),
|
||
})
|
||
|
||
// 关键业务字段断言
|
||
orderId := resp.GetBody().GetMap("result").GetCeilInt64("id")
|
||
if orderId <= 0 {
|
||
resp.Fail("返回的订单 ID 必须大于 0")
|
||
}
|
||
sn := resp.GetBody().GetMap("result").GetString("sn")
|
||
if sn == "" {
|
||
resp.Fail("返回的订单编号 sn 不能为空")
|
||
}
|
||
}},
|
||
}
|
||
```
|
||
|
||
## 文档结构
|
||
|
||
### 不变章节(微调措辞)
|
||
|
||
- 概述(能力表格)
|
||
- 核心类型
|
||
- 链式 API 参考(在 expect 参数规则部分强调:错误用例建议三参数写满)
|
||
- 事务隔离机制
|
||
- 覆盖率报告
|
||
- API 调试控制台
|
||
- 指定运行范围
|
||
- 并发保护与缓存隔离
|
||
- 框架改动说明
|
||
|
||
### 重写/新增章节
|
||
|
||
#### 1. "快速开始" — 使用上述完整范例
|
||
|
||
- 先展示业务代码(handler),再展示测试代码
|
||
- 范例中完整体现五步流程
|
||
- 目录结构、注册方式、运行方式保持原有说明
|
||
|
||
#### 2. "用例编写范式" — 新增章节,替代原"完整场景对照"
|
||
|
||
按顺序逐步讲解范例中的每个环节:
|
||
|
||
- **错误用例编写规范**:为什么三参数必须写满(错误码复用)、如何覆盖权限/参数/业务错误
|
||
- **测试数据准备**:`a.DB().Insert()` 的使用场景和注意事项(事务内操作,自动回滚)
|
||
- **正确请求 + 响应结构校验**:第三参数 Map 的类型样本规则、ExpectResult 后置校验
|
||
- **响应字段断言**:`resp.GetBody()` / `resp.Fail()` 的用法、哪些字段必须断言
|
||
- **数据库状态校验**:Verify 的使用时机(只要改了DB就建议校验)、校验主表+关联表+字段值
|
||
- 包含"不好的写法 vs 推荐的写法"对比
|
||
|
||
#### 3. "API 速查表" — 精简版场景对照
|
||
|
||
保留各种参数组合(JSON/Form/Query/File/混合/Session 等)的快速参考,但每种只一行示例代码,不再是大段散乱的代码块。
|
||
|
||
## 改动范围
|
||
|
||
- 仅改动 `docs/Testing_API测试框架.md`,约 750-850 行
|
||
- 不涉及 Go 源码
|
||
- 不涉及其他文档
|
||
|