接口测试-录制回放-diffy

前言

这个项目是在2021年我在某基金公司参与的一个项目。当时我们的项目从C#转向Java,开发采用了全面的前后端分离架构,同时还采用了Spring Cloud的相关套件(Apollo、Eureka),并使用了公司自研的一个名为stone的框架,主要在servlet层收集日志,并将接口相关的信息写入数据库中。此时开发开发需要比较快,但是问题又很多,需要测试团队快速回归测试。然而,我们的测试开发团队只有四个人,其中自动化测试的人手不足。使用传统的编写脚本的方式进行接口测试或UI测试的速度远远落后于开发需求的速度。在这样的条件下,我们偶然发现了Diffy这个工具,并且使用它带来了明显的收益。

重新思考传统的接口测试

传统的接口测试主要是我们构造不同的请求,发起请求,拿到响应后,将响应和预期的结果进行对比一致则为通过。然而如果一个接口已经回归过测试很多版本,那么这个接口可能不会变动,代码和需求不变更的情况下,上一个版本的响应则可以作为基线和这一个版本的响应对比,判断接口返回是否符合预期。

录制回放接口分类

读类接口是指用于获取数据的接口,它定义了一些读取数据的方法或属性。读类接口通常用于从外部系统或数据源中获取数据,并将其提供给其他模块或类使用。读类接口的典型应用场景包括数据库读取、API调用等。常见的请求方式包括:GET,POST等。对应DIffy、GoReplay、. Sharingan等流量录制回放工具

写类接口是指用于写入数据的接口,它定义了一些写入数据的方法或属性。通过写类接口,可以将数据写入到外部系统或数据源中。写类接口的典型应用场景包括数据库写入、文件操作等。常见的请求方式POST,DELETE,PUT等。包括Doom,jvm-sandbox-repeater等

录制回放的两个步骤

流量录制

流量录制指的是在不影响正常用户使用的前提下,捕获线上用户的真实请求和服务响应结果。这一过程可以通过多种方式进行,但通常涉及以下要点:

  • 选择录制方式:根据需求选择适合的流量录制手段,这可能基于应用层的复制,或者更底层的网络抓包等方式。
  • 确定录制内容:定义需要录制的流量范围,例如特定的API接口、用户会话或操作流程。
  • 实施录制:启动录制过程,捕获请求和响应数据,并将其保存为日志或转储文件。
  • 处理敏感数据:在录制的流量中,可能会包含敏感信息(如用户个人信息),因此需要对这些数据进行脱敏处理。
  • 存储和管理录制数据:将录制的数据存储在安全的环境中,并提供相应的查询和管理能力。

流量回放

流量回放则是将录制下来的流量重新发送到目标系统,以进行进一步的测试和分析。在这个过程中,需要注意以下几个关键点:

  • 选择回放方式:根据测试目的选择在线或离线回放方式。在线方式直接将流量实时转发到目标服务;离线方式则先保存流量,后续再处理或筛选后发送。
  • 配置回放环境:准备用于回放流量的测试环境,确保其与录制时的环境相仿或按需配置相应的替代方案。
  • 执行回放:启动流量回放,观察系统的响应情况,检查服务是否能够正确处理请求,并记录性能指标。
  • 分析回放结果:对回放过程中的错误和异常情况进行分析,评估系统的稳定性和性能。
  • 调整和优化:根据回放结果进行必要的系统调整和优化。

在我们当时的项目因为开发已经将测试数据收集到了数据库中,并且是脱敏数据,所以我们只需要考虑流量回放。

Diffy的介绍

Diffy需要部署三个版本的系统来实现它的噪声过滤和对比功能,这三个版本分别是:候选版本(candidate)、稳定版本(primary)和稳定版本副本(secondary)。候选版本是待测版本,有着最新待测代码;稳定版本通常是已经上线的版本,或者是已知功能正常的版本;稳定版本副本是稳定版本的副本,和稳定版本运行相同的代码,主要用于排除噪声。当Diffy接收到请求后,会把请求分发到这三个地方:被测服务(候选版本)、稳定版本服务和稳定版本副本服务。然后,候选版本服务与稳定版本服务的返回结果进行diff,生成原始diff结果(raw differences),即原始区别。接着,稳定版本与稳定版本副本的返回结果进行diff,生成噪声diff差异值结果(non-deterministic noise),即噪声。通过对这些差异值做减法来消除噪声。最后,通过比对原始的diff结果与消除噪声后的结果,得到最终的diff结果。
在这里插入图片描述
具体可以参考如下链接:https://gitee.com/mirrors_opendiffy/diffy#what-is-diffy

我们项目是如何使用DIffy这个工具的

因为开发已经使用了Spring的架构,而且我们可以拿到开发Build不同服务对应的Jar包,为了保证两个版本的Jar包使用同样的配置文件,我们只需要在Jar包的配置文件中配置对应的eureka环境,并在Apollo设置保证两个版本的Jar包使用同一套配置文件。

Diffy安装、使用

安装

尝试使用windows编译diffy,但是会遇到各种问题导致不能编译成功,最后在阿里云 linux云服务器编译的,执行很顺利,可以参考如下步骤:
1.git clone https://gitee.com/mirrors_opendiffy/diffy.git 没有git的话,先安装git,sudo yum install git 注意:一定要使用git拉代码到本地,否则会报无法找到git文件的错误

2.下载完成后,进入diffy目录,执行./sbt assembly进行编译,编译过程很慢,

可以vim ~/.sbt/repositories 修改 repositories的内容如下:

[repositories]
local
my-maven-repo: http://maven.aliyun.com/nexus/content/groups/public/
central: http://repo1.maven.org/maven2/

然后在diffy目录下修改vim ./sbt 添加-Dsbt.override.build.repos=true

在这里插入图片描述
重新执行./sbt assembly编译,整个过程就会快很多,编译完成后/diffy/target/scala-2.12目录下会生成diffy-server.jar文件,需要使用该jar包启动diffy代理服务。

使用

在diffy/example文件夹下有diffy启动的配置文件run.sh,主要参数如下:

-candidate=‘localhost:9200’ \ candidate环境的地址,为测试环境的服务地址
-master.primary=‘localhost:9000’ \ primary环境的地址,通常是已经上线版本,或者是已知功能正常的版本
-master.secondary=‘localhost:9100’ \ secondary环境的地址,和primary环境的地址一致即可
-responseMode=‘candidate’ \ diffy代理返回的结果为测试环境的结果
-service.protocol=‘http’ \
-serviceName=‘ExampleService’ \ diffy展示报告的名称
-summary.delay=‘1’ \
-summary.email=‘example@diffy.ai’ \ 转发报告到XX邮件 如XX@qq.com
-maxHeaderSize=‘32.kilobytes’
-maxResponseSize=‘5.megabytes’
-isotope.config=‘/Users/puneetkhanduri/code/sn126/isodemo/local.isotope’
-proxy.port=:8880 \ diffy的代理端口,请求需要发给该端口
-admin.port=:8881 \ 后台登录的端口
-http.port=:8888 & \ 展示报告的端口

修改好参数后可以通过 ./run.sh 启动diffy服务

整个过程可以参考如下链接:https://gitee.com/mirrors_opendiffy/diffy/blob/master/QUICKSTART.md

三部曲看DIffy的使用

单接口的流量录制回放对比

  1. 首先使用fastapi启动两个服务模仿开发的后端接口服务,代码如下,代码主要是读取两个不同的json文件并返回内容
app = FastAPI()

@app.get("/data")
def read_json_file():
    with open('secondary.json', 'r') as file:
        data = json.load(file)
    return data

if __name__ == '__main__':
    uvicorn.run("primary_demo1:app", host="localhost", port=8880)
  1. 在diffy的启动文件中编写不同接口服务器对应的信息,并启动,主要如下:
    echo Build Diffy
    echo Deploy Diffy
    java -jar diffy-server.jar ^
    -candidate="localhost:9990" ^
    -master.primary="localhost:8880" ^
    -master.secondary="localhost:8880" ^
    -responseMode="candidate" ^
    -service.protocol="http" ^
    -serviceName="penn_demo" ^
    -summary.delay="1" ^
    -summary.email="example@diffy.ai" ^
    -maxHeaderSize="32.kilobytes" ^
    -maxResponseSize="5.megabytes" ^
    -proxy.port=:5550 ^
    -admin.port=:5551 ^
    -http.port=:5555 ^
  1. postman向端口发起请求
  2. 查看对比结果

多接口的流量录制回放对比

录制回放的价值主要体现在对多接口的录制回放对比,以上已经提及我们已经获取了录制的数据,只需要拿录制的数据对diffy进行请求,然后对比不同版本的jar包以发现缺陷,这个过程中主要部分为批量发起请求的脚本(服务),批量发送请求对比不同版本接口的差异。

个性化改造diffy

如果数据量比较大,diffy的排序会比较错乱,或者有时候diffy会拿一些我们不想用于对比的东西进行对比,这时候我们可以对diffy进行个性化改造,改造过程如下:

  1. 更改diffy的配置文件,其中candidate和primary对应的,是自己将个性化处理接口的一套服务,这样的化,当diffy将请求发过来的时候,可以根据请求的内容进行个性化处理以及转发
java -jar ./diffy-server.jar ^
-candidate=localhost:8880 ^
-master.primary=localhost:9990 ^
-master.secondary=localhost:9990 ^
-responseMode=candidate ^
-service.protocol=http ^
-serviceName=demo ^
-summary.delay=10 ^
-allowHttpSideEffects=true ^
-maxHeaderSize=32.kilobytes ^
-maxResponseSize=5.megabytes ^
-summary.email=info@diffy.ai ^
-rootUrl=“localhost:5555” ^
-proxy.port=:5550 ^
-admin.port=:5551 ^
-http.port=:5555 ^

@pause
  1. candidate和primary对应的对应的代码是一致的,主要部分如下,因为@app.get(“/”)部分定义的是根路径,发送请求的时候可以直接指向根路径,然后把其他包装在请求体里面,在proxy里面根据自己的需求定制化开发。如何proxy无论发来请求是谁,都会指向http://localhost:9006/customer?custName=John接口
app = FastAPI()


@app.get("/")
def proxy(req: Request):
    rsp1 = requests.request('GET',
                            url='http://localhost:9006/customer?custName=John', data={},
                            headers=copy.deepcopy(req.headers)).text

    return json.loads(rsp1)


if __name__ == '__main__':
    uvicorn.run("fastapi_proxy_9990:app", host="localhost", port=9990)

用postman发起请求:
在这里插入图片描述
最后的结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值