一、背景
对于一个平台产品,接口的回归十分重要,但是目前现有回归平台要么太重,要么根据具体的接口去做用例设计和逻辑验证;前者需要公司有专门的测试平台支持部分,或者花钱购买,使用上也比较被动,后者涉及大量用例编写和代码编写实现缓慢,稳定性差。
二、方案概要
通过对迭代测试环境中的nginx中的日志内容,解析出查询接口数据,落库到数据库中,而后对接口数据进行清洗,得到的接口数据作为用例,分别在迭代测试环境和历史版本环境中执行,比对二者之间的返回结果差异,做数据的比对验证。
三、前提
- 1、平台使用Nginx 中间件做代理;(其他可以生成接口日志的也行)
- 2、拥有迭代测试环境和历史版本环境,且二者使用同一组底层数据库;
- 3、平台接口入参和返回接口数据具有大体的稳定性;
- 4、操作者有基本的编码能力和SQL编写能力(手动狗头);
四、核心问题解决
(一)nginx日志捕获
- 1、Nginx 配置通过日志打印捕获接口数据配置,网上很多,就不赘述了;
- 2、日志中信息解析根据日志中的字符串格式进行即可,只是读取文件并字符串解析,也不赘述了;
(二)数据清洗
- 1、SQL写得好,数据清洗没烦恼;
注:清洗掉不可用的用例,比如说路径为空,核心参数为空,不需要参数回归的接口等;
(三)数据比对
- 1、接口调用推荐使用工具包hutool,直接拿来用,支持并发,比较省事;
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
- 2、核心比对逻辑
public Boolean compareResult(String path, Object fact, Object refer){
if(fact instanceof Map && refer instanceof Map){
for(Map.Entry<String, Object> entry : ((Map.Entry<String, Object>)refer).entrySet()){
/*该处对于不需要对比的key可以设置特殊处理,可以对不同的接口通过多态做成不同的处理*/
if(!CompareResult(path+"."+entry.getKey(),((Map.Entry<String, Object>)fact).get(entry.getKey()),entry.getValue())){
return false;
}
}
}else if(fact instanceof ArrayList && refer instanceof ArrayList){
if(((ArrayList)fact).size() != ((ArrayList)refer).size()){
return false;
}
for(int i= 0; i<((ArrayList)fact).size();i++){
if(!CompareResult(path+"["+i+"]",((ArrayList)fact).get(i),((ArrayList)refer).get(i))){
return false;
}
}
}else if(fact instanceof String && refer instanceof String){
if(!String.valueOf(fact).equals(String.valueOf(refer))){
return false;
}
}else if ...
/*其他数据类型和空值场景就不赘述了, 这里是手写的,主要表达一种实现思路吧*/
}
对比差异结果中,将path和接口参数要素打印出来,可以很快定位失败用例的失败位置。
- 3、用例执行管理
@DataProvider(name = "queryBatchData", parallel = true)
public Object[][] queryBatchData(){
/*从数据库中查询用例数据即可,构建用例数据model,一个model为一个用例*/
}
@Test(description = "批量执行回放用例", dataProvider = "queryBatchData")
public void executeQueryBatchCases(CaseModel caseModel){
/*分别查询两个环境,获取返回结果并比对即可*/
}