zoukankan      html  css  js  c++  java
  • Go测试技术分享(一):场景化接口Case编写

    一、前言

      本人负责的支付清结算方向的测试工作,在测试项目中,会出现流程化的接口调用,请求完一个接口后,继续请求另一个接口(这里的接口可以指Http,也指rpc接口),这里以一个真实场景为例:用户在平台下单,结算前部分退款,再结算,最后结算后部分退款;

      第一个接口动作对应用户下单,第二个动作对应结算前的部分退款,第三个动作对应结算,第四个动作对应结算后的部分退款,涉及不同系统的交互;这是一个完整的场景,根据我们的测试用例与更多的用户场景,实际测试中,我们需要测试更多场景,单接口测试已无法满足实际需求。

    二、表格驱动测试

      我们可以定义一个结构体,将每一个步骤定义成一个节点,通过遍历节点达到执行整个流程的效果:

      优点就是代码更加清晰、明确,也便于调整步骤的顺序、新增或者移除某些步骤。另外,在循环体中增加调试日志也非常的简单;

      但还是有缺点的,看上去似乎不满足接口测试一些要求,没有case管理,无法做接口断言等  

    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)
      }
     }
    }

    三、封装

    将场景和节点定义成结构体,提供场景与节点独立的执行接口:

    实际的节点,需要定义成这个结构体的方法;

    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"

    这里仍然以上面的场景为例:

    //结算前部分退款,再结算,部分退款
    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")
    	})
    }
    

      

      

      

  • 相关阅读:
    js---11闭包
    js---10作用域链
    js---12数据类型,数据类型转换,NaN,
    js---11运算符,流程控制,真假
    js---10时间类
    js--09定时器
    js---08函数 定时器
    js---07 js预解析,作用域---闭包
    js---06函数传参数
    [虎嗅]职场中年独白:我们是被嫌弃的少数派
  • 原文地址:https://www.cnblogs.com/-wenli/p/15111773.html
Copyright © 2011-2022 走看看