质量体系建设之路---可视化的MockServer
一、 背景
福禄网络作为一家数字权益商品及服务提供商,覆盖了我们衣食住行的各种生活场景的权益内容,对接了如支付宝、京东、银行APP各种渠道,如何能够快速的响应渠道需求,提供稳定的接口服务,这就要求我们电商团队能够做到比渠道快一步的接口测试;
同时作为一家集团化的公司,内部的信息化系统对接了众多银行的相关支付业务,涉及到查余额、下流水、支付、对账等日常资金业务,这要求信息化部门能够确保资金支付相关场景能够在上线前进行完整覆盖,业务方新的业务接入或者需求场景变更比较频繁,版本的快速迭代背景下如何保证众多的场景能够快速覆盖,通过完全真实的业务操作成本是巨大的;
二、 引入MOCK
基于上述的业务系统测试痛点,质量管理团队决定引入mock服务。我们首先想到的是以最低的成本来完成,市面上有许多的mockserver的开源软件,但在调研了相关的开源产品之后,我们发现没有一款比较贴合我们业务需求的产品;
比如我们的资金支付相关场景对接的银行方,都是以xml报文的格式作为请求和返回;有些场景对返回模板的数据是动态要求的,比如某个支付状态第一次请求是处理中,第N次请求变为成功;而有些银行通信协议是socket等,通过调研后我们决定自己来开发一套mock服务。
三、框架选型
- 界面可视化操作
为了保持系统风格的统一,我们决定沿用QECS平台的前端框架(QECS详细介绍移步至:https://www.cnblogs.com/fulu/p/15419208.html) - 高性能
为了满足高性能的需求,模板数据存储我们采用redis;开始我们准备沿用QECS的后端框架flask,在进行了一系列的性能测试后,我们发现无法支撑我们5KTPS的需求,后来我们改用了springBoot,经过测试能够达到我们的需求;
四、具体实现
4.1 设计方案
外部请求打入Mock服务,监听服务获取到请求通过Redis中的已有模板进行规则匹配,满足匹配规则返回对应模板数据;不满足返回无法匹配的数据提示。
4.2 功能说明
数据格式
目前匹配规则支持json、form、query、xml这几种参数类型;返回支持json、xml和text这几种数据类型
状态码
可以模拟返回200、500、304、502、503、400等各种http状态码
返回时间
可以设置请求mock服务后的返回间隔时间,对超时返回场景比较有效
动态取值
设置了内置函数和从匹配规则中取值这两种方式,可以动态设置返回数据的字段值
自定义代码
对于平台界面暂时无法支撑的个性化需求,可以通过在Hermes中通过代码来实现,灵活方便
高性能
模板数据通过Redis进行存储,请求进来到模拟返回通过redis进行匹配,能够提供高性能的返回,可作为性能压测的挡板服务
4.3 平台功能介绍
4.3.1 主界面
4.3.2 创建API,即我们需要模拟调用的对方接口
4.3.3 配置模板,配置API的期望模板
模板数据会存储到REDIS
4.3.4 模拟请求
获取实际请求值,获取期望模板值,将模板与请求值进行比较匹配,当模板请求参数属于真实请求参数的子集,匹配成功
4.3.5 自定义函数的实现
为了满足个性化的使用场景,服务内置了一批内置函数来满足动态取值的场景
private static String getReplaceStr(String str){
if(str.contains("Random")){
String[] strA = str.trim().split(",");
int i1 = strA[0].indexOf("(");
int i2 = strA[1].indexOf(")");
String min = strA[0].substring(i1+1);
String max = strA[1].substring(0,i2);
return getRandom(Integer.valueOf(min), Integer.valueOf(max)).toString();
}
if(str.contains("CurrentDate")){
return getCurrentDate();
}
if(str.contains("SecondTime")){
return getSecondTime().toString();
}
if(str.contains("MicTime")){
return getMicTime().toString();
}
if(str.contains("CardID")){
return getCardID();
}
if(str.contains("Phone")){
return getPhone();
}
return str;
}
4.3.6 专家模式,对于目前界面暂时无法支撑的个性化需求,我们采取通过在后端服务编码的方式进行处理
@RequestMapping(value = {"/test"})
public void loadNum(HttpServletRequest request, HttpServletResponse httpServletResponse){
TimerTool timerTool = new TimerTool();
RestfulRequest restfulRequest = requestService.analyseRequest(request);
restfulRequest = filterHeader(restfulRequest);
log.info("分析请求cost:{}", timerTool.cut());
List<MockInfo> mockRules = mockInfoService.getMockRules(restfulRequest.getPath());
log.info("获取mock配置记录:{}, cost:{}", mockRules, timerTool.cut());
MockInfo mockRule = mockService.matchRulesNew(restfulRequest, mockRules);
log.info("匹配tag...cost:{}", timerTool.cut());
//先走平台模板,如果匹配不到,走专家模式(代码实现)的MOCK匹配逻辑
if(mockRule != null){
mockService.doResponseNew(mockRule, httpServletResponse);
}else {
mockExpertService.doResponse(restfulRequest, httpServletResponse);
}
}
专家模式实现个性化的mock逻辑
public void doResponse(RestfulRequest request, HttpServletResponse response){
try {
RestfulBody body = request.getBody();
String ip = request.getIp();
JSONObject requestParams = body.getParams();
String funName = requestParams.getJSONObject("CMBSDKPGK").getJSONObject("INFO").getString("FUNNAM");
Integer responseStatus = 200 ;
Integer responseSleep = 0;
String responseString = "mock数据去火星了!";
String responseInfo = mockInfoService.getMockExpert(ip,funName);
JSONObject responseInfoJson;
if(StringUtils.isEmpty(responseInfo)){
responseInfoJson = new JSONObject(true);
responseInfoJson.put("count", 0);
responseInfoJson.put("firstTime", TimeUtils.nowTimeStamp() / 1000);
responseInfoJson.put("response", getJsonResponse("xmlResource/resp_" + funName + ".xml"));
}else {
responseInfoJson = JSONObject.parseObject(responseInfo);
}
int count = responseInfoJson.getInteger("count");
JSONObject responseObj = responseInfoJson.getJSONObject("response");
// 批量查询余额
if("NTQADINF".equals(funName)){
long time_lag = (TimeUtils.nowTimeStamp() / 1000) - responseInfoJson.getLong("firstTime");
Object obj = responseObj.getJSONObject("CMBSDKPGK").get("NTQADINFZ");
// 距离第一次请求超过60s 余额+5000
if(time_lag > 60){
if(obj instanceof JSONArray){
JSONArray jsonA = (JSONArray)obj;
for(int i=0; i<jsonA.size();i++){
Double avlblv_value = jsonA.getJSONObject(i).getDoubleValue("AVLBLV");
avlblv_value = avlblv_value + 5000;
jsonA.getJSONObject(i).put("AVLBLV", String.format("%.2f",avlblv_value));
}
responseObj.put("NTQADINFZ", jsonA);
}
if(obj instanceof JSONObject){
JSONObject jsono = (JSONObject)obj;
Double avlblv_value = jsono.getDoubleValue("AVLBLV");
avlblv_value = avlblv_value + 5000;
jsono.put("AVLBLV", String.format("%.2f",avlblv_value));
responseObj.put("NTQADINFZ", jsono);
}
}
};
五、未来展望
目前这个版本我们适配了http协议下的大部分数据格式,如上所述,对于一些个性化的需求我们暂时采取的专家模式代码实现,一方面体现了自有平台的灵活性,另一方面我们也会在不断的使用过程中进行抽象提炼成共性的需求继续可视化的实现。
内置函数随着平台的使用范围和深度,相信会有更多需求场景需要相关函数的实现加以满足,不断去丰富这些函数,也是平台健壮的一个表现;
另外对于其他相关协议的补充也是平台需要进行后续规划完善的发力点。
你们有哪些mock的实际使用场景,欢迎交流
福小龙
质量体系建设之路---可视化的MockServer的更多相关文章
- 质量保障&&质量体系建设
一.质量保障 先引用一段 百度百科 上对软件质量保障的解释:软件质量保障是建立一套有计划,系统的方法,来向管理层保证拟定出的标准.步骤.实践和方法能够正确地被项目所采用.软件质量保证的目的是使软件过程 ...
- 民生银行十五年的数据体系建设,深入解读阿拉丁大数据生态圈、人人BI 是如何养成的?【转】
早在今年的上半年我应邀参加了由 Smartbi 主办的一个小型数据分析交流活动,在活动现场第一次了解到了民生银行的阿拉丁项目.由于时间关系,嘉宾现场分享的内容非常有限.凭着多年对行业研究和对解决方案的 ...
- 地图POI类别标签体系建设实践
导读 POI是“Point of interest”的缩写,中文可以翻译为“兴趣点”.在地图上,一个POI可以是一栋房子.一个商铺.一个公交站.一个湖泊.一条道路等.在地图搜索场景,POI是检索对象, ...
- Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设
Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设 1. 荣典体系的标准1 2. 勋章称号1 2.1.1. 授予标准1 3. 政出多门 统一的荣誉制度 2 3.1. 法则规定2 3.2. ...
- 【行业交流】2016 TiD质量竞争力大会——移动互联网测试到质量的转变之路
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5691233.html TiD质量大会在北京召开,有幸去参加 ...
- Hi,这有一份风控体系建设干货
互联网.移动互联网.云计算.大数据.人工智能.物联网.区块链等技术已经在人类经济生活中扮演越来越重要的角色,技术给人类带来各种便利的同时,很多企业也饱受"硬币"另一面的伤害,并且形 ...
- 如何推进企业流程体系建设?_K2 BPM
推进全集团统一的流程体系为什么比想象的难? 很多企业在推进全集团的流程管理过程中,经常会有一种“望山跑死马”的感觉.“各成员公司都建立起与集团公司统一的流程管理体系”,看似很简单一件事情,但没有经过良 ...
- Atitit 快速开发体系建设路线图
Atitit 快速开发体系建设路线图 1.1. 项目类型划分 哑铃型 橄榄型 直板型(可以立即实行)1 1.2. 解决方案知识库 最佳实践库 最佳流程优化(已成,需要一些整理)2 1.3. 功能模板 ...
- Atitit 提升效率 界面gui方面的前后端分离与cbb体系建设 规范与推荐标准
Atitit 提升效率 界面gui方面的前后端分离与cbb体系建设 规范与推荐标准 1. 界面gui方面的前后端分离重大意义1 2. 业务逻辑也适当的迁移js化1 3. 常用分离方法2 3.1. 页面 ...
随机推荐
- csp总结 (差点爆零的总结)
T1,iterator忘了怎么写了,想了很久都想不出来有什么可以替代,只好O(n^2): T2,不会,只会打暴力 T3,自以为是正解,写了很久大概3h,却一直过不了大样例,大样例输出全是0: T4,不 ...
- Luogu P1525 [NOIp2010提高组]关押罪犯 | 并查集
题目链接 这一道题,我用了并查集来做.在此题中,并查集的作用就是:将同一个监狱里的罪犯合并到一起. 思路:将每对罪犯之间的怨气值从大到小排序,再依次把他们分到不同的两个监狱里,当发现这一对罪犯已经在同 ...
- hdu 1394 Minimum Inversion Number(线段树or树状数组)
题意: 给你N个数,N个数是0~N-1的一个全排列. 要求统计它的所有形式的逆序对的最小值.它的所有形式的意思是,不断将数组开头的第一个数放到数组的最后面. 逆序对:i<j且ai>aj 思 ...
- Linux 服务器的基本性能及测试方法
1. 摘要 一个基于 Linux 操作系统的服务器运行的同时,也会表征出各种各样参数信息.通常来说运维人员.系统管理员会对这些数据会极为敏感,但是这些参数对于开发者来说也十分重要,尤其当程序非正常工作 ...
- vm workstation pro 安装centos7
workstation pro 下载地址 划到页面下方点击下载 安装教程 激活码 16版本 ZF3R0-FHED2-M80TY-8QYGC-NPKYF 15版本 FG78K-0UZ15-085TQ-T ...
- go struct结构
p.p1 { margin: 0; font: 12px ".PingFang SC"; color: rgba(69, 69, 69, 1) } span.s1 { font: ...
- [python]Robotframework+Git+jenkins实现持续集成并生成测试报告发送邮件
1.环境需求 &robotframework(不写搭建,自行百度) & git(不写安装,自行百度) &jenkins 2.安装jenkins 官网下载最新版本https:// ...
- BAT面试必问细节:关于Netty中的ByteBuf详解
在Netty中,还有另外一个比较常见的对象ByteBuf,它其实等同于Java Nio中的ByteBuffer,但是ByteBuf对Nio中的ByteBuffer的功能做了很作增强,下面我们来简单了解 ...
- [JS]什么是闭包?
首先来思考一下下面的案例: function unclosure() { let count = 0 return count++ } for (let index = 0; index < 1 ...
- 实验1:SDN拓扑拓扑实验
一.实验目的 能够使用源码安装Mininet: 能够使用Mininet的可视化工具生成拓扑: 能够使用Mininet的命令行生成特定拓扑: 能够使用Mininet交互界面管理SDN拓扑: 能够使用Py ...