摘要:解决链路间参数传递的问题可以简化为解决接口间的参数传递问题。当然,针对这个问题的解决方案,其实还是蛮多的。总结下来,自动化用例的维护和开发成本主要集中在接口间参数传递的维护上面。
做过接口自动化测试的同学肯定都熟悉在全链路测试过程中,很多业务场景的完成并非由单一接口实现,而是由很多接口组成的一条链路实现。例如你在淘宝上购物场景。
不同于单接口测试,这种链路型的接口自动化测试,由于接口间有参数依赖关系,往往不能将链路中的接口入参固定写死,而是要依赖“上游”的响应中的某个字段值,因此需要提取出来动态地传递给下个接口,如下图。
解决链路间参数传递的问题可以简化为解决接口间的参数传递问题。当然我上图举例是比较简单的,下游对上游的依赖关系为1对1这种类型。实际业务场景中,更多的是多对一这种场景,即下游依赖上游的多个接口的返回结果。
当然,针对这个问题的解决方案,其实还是蛮多的。就以JMeter工具为例,它就提供了通过后置处理器的多种参数提取方法。
其解决方案是,通过正则、JSON Extracor等提取的结果作为变量,动态传递数值给下游(变量)使用。
当然,这种解决方案对于JMeter工具来说,是个不错的解决方案,而且这个解决方案也具备普适性,就算你开发自己的接口测试框架,也是可以使用这种解决方案的(实际上,我在前东家参与研发的接口测试框架,当时解决接口间参数传递的问题就是借鉴的这种思路。开发了一个类似JMeter正则提取器的正则提取工具包,引用工具包可以允许你输入要提取的字段key便可匹配到其字段值value,如果提取不到就返回默认值,如果有响应体中一个key存在多个value,则返回最后一个匹配到的value;下游接口则使用Java replace()方法替换掉请求体中的${xx}。)。
如果只追求可以用,这个方案没问题。但是这个方案缺点就是接口用例开发效率比较低,增加了写接口测试用例的成本。这也是我当时遇到的一个问题,大家写自动化测试用例的时间很大一部分花在接口间参数提取和调试上。此外,这个方案也会增加维护成本,导致用例的“稳定性”比较低。是因为如果上游接口的响应体结构变化可能会影响提取结果,下游的接口请求体中的${xx}也需要手动维护。总结下来,自动化用例的维护和开发成本主要集中在接口间参数传递的维护上面。
是否有更优的解决方案呢?
试想一下,我们能否将整条链路可能使用到的字段集合作为一个池子,在上游接口的响应结果提取出key-value并扔到池子里。下游的接口request体模版化,以${xxx}表示需要替换的变量,利用模板引擎(例如Java的velocity/FreeMarker)将${xxx}替换成“池子”中存在的value。实现的简图如下。
动手做
下面就以Java语言实现为例,写两个方法A、B,且B依赖方法A的返回结果。
我们只需要开发 上下文类、模版组装工具、模拟场景代码即可。
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.beanutils.BeanUtils;
import java.util.Map;
public class Client {
public static JSONObject login(){
JSONObject result = new JSONObject();
result.put("token","xsjkjdskdjsksjfksjfksjk");
return result;
}
// pay接口,依赖login接口
public static JSONObject pay(String request){
JSONObject result = new JSONObject();
// 就简单写了
if (request.contains("xsjkjdskdjsksjfksjfksjk")){
result.put("order", "122324434335");
result.put("status", "success");
} else {
result.put("status", "fail");
}
return result;
}
// 场景模拟
public static void main(String[] args) {
// 首先调用登陆接口
JSONObject loginResponse = login();
// 步骤1.将结果写入上下文
Context context = new Context();
context.setToken(loginResponse.getString("token"));
// 创建一个pay接口的request模版
String request = "{/"token/":/"${token}/"}";
try {
// 步骤2.利用Apache BeanUtils工具 BeanToMap方法 将上下文转化为keyValues
Map
keyValues=null; keyValues = BeanUtils.describe(context);
// 步骤3.组装模版,将${token}替换为上下文中的其key存在的value
String out_request = VelocityUtils.parse(request, keyValues);
System.out.println("组装request请求模版:" + out_request);
// 发起下单支付
JSONObject result = pay(out_request);
// 打印接口返回结果
System.out.println("打印响应结果:" + result.toString());
}catch (Exception e){
System.out.println("异常退出");
}
}
}
这种方案的优点:
我们只需要care步骤1即可(将上游的响应结果写入上下文),后面的组装模版这些可以写成同样的工具,只需要传入模版+上下文内容即可,无需关注其他,能大大节省自动化用例开发和维护的成本。
当然,本文只是抛砖引玉,如果有其他方案,也希望大家多多发散,多多交流沟通。
工具清单:
commons-beanutils
org.apache.velocity
com.alibaba.fastjson
org.projectlombok.lombok
往期推荐
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/125565.html
摘要:同时吸取了社区大量优秀思想,进行归纳比对。有兴趣的读者可以点击下面的链接购买,再次感谢各位的支持与鼓励恳请各位批评指正京东当当原文网址 在React中最小的逻辑单元是组件,组件之间如果有耦合关系就会进行通信,本文将会介绍React中的组件通信的不同方式 通过归纳范,可以将任意组件间的通信归类为四种类型的组件间通信,分别是父子组件,爷孙组件,兄弟组件和任意组件,需要注意的是前三个也可以算...
摘要:设计模式的类别设计模式一共分为种类型,共种。属于结构型的设计模式适配器模式桥接模式装饰模式组合模式外观模式享元模式代理模式。问题描述了应该在何时使用设计模式。解决方案描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。 设计模式概述 1. 设计模式是什么 我们在平时编写代码的过程中,会遇到各种各样的问题,细想一下很多问题的解决思路大致一样的,这时候你就可以把解决问题的思路整...
摘要:原文地址前言起源组件化方案分析业务组件的划分和代码隔离路由框架基础库的优势简介什么是组件化为什么要组件化分析现有的组件化方案如何选择组件化方案组件化方案描述架构图一览架构图详解宿主层业务层业务模块的拆分基础层核心基础业务公共服务基础组件其他 原文地址: https://www.jianshu.com/p/f67... 0 前言 0.1 起源 0.2 组件化方案分析 0.2....
摘要:想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。创建型设计模式主要有简单工厂模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式和单例模式,下面一一道来。而工厂方法模式本意是将实际创建对象的工作推迟到子类中。 接触前端两三个月的时候,那时候只是听说设计模式很重要,然后我就去读了一本设计模式的书,读了一部分,也不知道这些设计模式到底设计出来干嘛的,然后就没再看了。后...
阅读 3733·2023-01-11 11:02
阅读 4243·2023-01-11 11:02
阅读 3049·2023-01-11 11:02
阅读 5179·2023-01-11 11:02
阅读 4733·2023-01-11 11:02
阅读 5532·2023-01-11 11:02
阅读 5312·2023-01-11 11:02
阅读 3985·2023-01-11 11:02