质量体系建设之路---可视化的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. 页面 ...
随机推荐
- iPhone SE切换颜色特效
Apple 网站的特效, iPhone SE 共有黑.白.红三种颜色,在卷动页面的时候会逐步替换,看起来效果非常时尚,在此供上代码学习. <!DOCTYPE html> <html& ...
- BF算法和KMP算法
这两天复习数据结构(严蔚敏版),记录第四章串中的两个重要算法,BF算法和KMP算法,博主主要学习Java,所以分析采用Java语言,后面会补上C语言的实现过程. 1.Brute-Force算法(暴力法 ...
- 前端---梳理 http 知识体系 1
最近看了http相关的知识点,觉得还是有必要整理下,这样对自己的网络知识体系也有帮助. http 是什么 http叫超文本传输协议,可以拆成超文本.传输.协议来理解 协议 http 是一个用在计算机里 ...
- 攻防世界 Misc 新手练习区 give_you_flag Writeup
攻防世界 Misc 新手练习区 give_you_flag Writeup 题目介绍 题目考点 gif图片分离 细心的P图 二维码解码 Writeup 下载附件打开,发现是一张gif图片,打开看了一下 ...
- webpack 提取css成单独文件
webpack 提取css成单独文件 // 用来拼接绝对路径的方法 const {resolve} = require('path') const HtmlWebpackPlugin = requir ...
- Python爬虫中的URLError\HTTPError异常类,异常的抛出
# _*_ coding : utf-8 _*_# @Time : 2021/11/2 14:20# @Author : 秋泊酱 import urllib.request import urllib ...
- python 字符串和时间格式(datetime)相互转换-
2019-03-17 11:00:00格式转化 import datetime # str转时间格式: dd = '2019-03-17 11:00:00' dd = datetime.datetim ...
- Typora常用操作
Typora常用操作 目录 Typora常用操作 1. 标题 2.子标题 3. 区块 4.代码 5. 表格 6. 超链接 7.单选框 8.数学公式 9.流程图 10.生成目录 11.字体设置 12. ...
- c语言循环位移(数字,字符串)
C语言中没有提供循环移位的操作符,但可以通过简洁的方式实现循环移位 设一个操作数x有s位则循环左移n位的操作为: (x << n) | (x >> (s - n)); 同理右移 ...
- cmd命令配置MySQL
当安装完MySql后,每次windows启动的时候都会将MySql服务启动起来. 如果是winxp则不需要使用管理员权限既可以很简单的打开和关闭,具体在cmd中敲入命令: 1.启动MySql服务: n ...