Go测试技术分享(一):场景化接口Case编写
一、前言
本人负责的支付清结算方向的测试工作,在测试项目中,会出现流程化的接口调用,请求完一个接口后,继续请求另一个接口(这里的接口可以指Http,也指rpc接口),这里以一个真实场景为例:用户在平台下单,结算前部分退款,再结算,最后结算后部分退款;
第一个接口动作对应用户下单,第二个动作对应结算前的部分退款,第三个动作对应结算,第四个动作对应结算后的部分退款,涉及不同系统的交互;这是一个完整的场景,根据我们的测试用例与更多的用户场景,实际测试中,我们需要测试更多场景,单接口测试已无法满足实际需求。
二、表格驱动测试
我们可以定义一个结构体,将每一个步骤定义成一个节点,通过遍历节点达到执行整个流程的效果:
优点就是代码更加清晰、明确,也便于调整步骤的顺序、新增或者移除某些步骤。另外,在循环体中增加调试日志也非常的简单;
但还是有缺点的,看上去似乎不满足接口测试一些要求,没有case管理,无法做接口断言等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | func main() { ctx := &context{} steps := [] struct { name string fn func () error }{ { "parse flags" , ctx.parseFlags}, { "read schema" , ctx.readSchema}, { "dump schema" , ctx.dumpSchema}, // Before transformations { "remove builtin constructors" , ctx.removeBuiltinConstructors}, { "add adhoc constructors" , ctx.addAdhocConstructors}, { "validate schema" , ctx.validateSchema}, { "decompose arrays" , ctx.decomposeArrays}, { "replace arrays" , ctx.replaceArrays}, { "resolve generics" , ctx.resolveGenerics}, { "dump schema" , ctx.dumpSchema}, // After transformations { "decode combinators" , ctx.decodeCombinators}, { "dump decoded combinators" , ctx.dumpDecodedCombinators}, { "codegen" , ctx.codegen}, } for _, step := range steps { ctx.debugf( "start %s step" , step.name) if err := step.fn(); err != nil { log.Fatalf( "%s: %v" , step.name, err) } } } |
三、封装
将场景和节点定义成结构体,提供场景与节点独立的执行接口:
实际的节点,需要定义成这个结构体的方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | type SenceSuite struct { SenceSuite string } type Plan struct { Planname string Fn func ( map [string] interface {}) interface {} Data map [string] interface {} } var SenceSuiteDao *SenceSuite var SenceSuiteOnce sync.Once func NewSenceSuiteDao() *SenceSuite { SenceSuiteOnce.Do( func () { SenceSuiteDao = &SenceSuite{} }) return SenceSuiteDao } func (dao *SenceSuite) DoSence(steps []Plan) { for _, step := range steps { step.Fn(step.Data) } } func (dao *SenceSuite) DoPlan(step Plan) interface {} { return step.Fn(step.Data) } |
四、实际使用
接口case管理:"github.com/smartystreets/goconvey/convey"
这里仍然以上面的场景为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //结算前部分退款,再结算,部分退款 func TestRefundAndNomalSettleAndRefund(t *testing.T) { // 初始化数据库 utils.DBInit() //用户下单 order := GetOrder( "ZFB" , "SELF" , "nrmol" ) env := "prod" way := "1" SenceSuite := utils.NewSenceSuiteDao() convey.Convey( "结算前部分退款" , t, func () { P1 := utils.Plan{Planname: "结算前部分退款" , Fn: SenceSuite.Refund, Data: map [string] interface {}{}} res := SenceSuite.DoPlan(P1).(*xxx) convey.So(res.RetCode, convey.ShouldEqual, "000000" ) }) convey.Convey( "正常结算" , t, func () { P2 := utils.Plan{Planname: "正常结算" , Fn: SenceSuite.Settle, Data: map [string] interface {}{}} res := SenceSuite.DoPlan(P2).(*xxx) convey.So(res.RetCode, convey.ShouldEqual, "000000" ) }) convey.Convey( "结算后部分退款" , t, func () { P3 := utils.Plan{Planname: "结算后部分退款" , Fn: SenceSuite.Refund, Data: map [string] interface {}{}} res := SenceSuite.DoPlan(P3).(*xxx) convey.So(res.RetCode, convey.ShouldEqual, "000000" ) }) } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2020-08-07 Python Http请求json解析库
2020-08-07 监听Rabbitmq系统日志(python版)
2020-08-07 Mysql主从复制