1、Diffy 是什么
- Diffy 是 Twitter 的一个开源自动化测试工具,是一种 Diff 测试技术。Diffy 通过同时新代码和旧代码的实例,对比运行结果来发现服务中的潜在错误。
- Diffy 充当代理并将它收到的任何请求多播到每个正在运行的实例
2、Diffy 解决什么问题
随着项目的迭代,产品功能不断增加,项目会变得越来越复杂;而从质量保障的角度,除了要保障好每次新增、优化的产品质量外,还需要确认新增或修改的功能不影响之前已存在的功能。若要进行产品功能全量回归,这个测试的工作量将会非常巨大。
因此 Diffy 提供了较好的解决方案,它基于稳定版本和它副本的输出,对候选版本的输出进行严格对比,以检查候选版本是否正确,大大降低了回归工作量3、Diffy 工作原理
Diffy 充当代理,它能够将来源请求分发到三个不同的服务实例中,通过对各个版本系统的输出进行对比,做出最终的结论。整个运行流程为:
Diffy 需要三个版本的实例,以实现它的噪声过滤和对比功能,它们分别是:
- 候选版本(candidate):该版本是待测版本,相对于生产环境版本有着更新的代码
- 稳定版本(primary):该版本通常是已经上线版本,或者是已知功能正常的版本
- 稳定版本副本(secondary):该版本是稳定版本的副本,和稳定版本运行相同的代码,主要用于排除噪声
如上图所示,Diffy 能够比较 primary (线上稳定版本) 和 secondary (线上稳定版本备份) 的差异值,通过对这些差异值做减法来确定接口的噪声(比如时间戳、随机 ID 等)
通过比较 candidate (测试版本) 和 primary(线上稳定版本) 得到基本的 diff 结果;最后通过比对基本的 diff 结果与消除噪声后的结果,得到最终的 diff 结果
其中:
- 原始区别:为候选版本 和 稳定版本之间输出的区别,其中可能会包含噪声
- 噪声:从稳定版本 和 其副本中获得,如果两个运行相同代码的系统输入相同输出却不同,则 Diffy 会认为这是开发人员不需要关心的噪声(比如时间戳、随机 ID 等)
- 基于上述两个区别集合,Diffy 可以识别出 候选版本 和 稳定版本 真实的区别,这些区别很有可能就是一个缺陷
当然,对于一个概率性出现随机值,仅仅一次请求的结论可能是不准确的。 例如:
对于一个 50% 概率出现 true 或者 false 的布尔值,则有 50% 的概率会出现候选版本和稳定版本的不同,同时又会有 50% 的概率出现稳定版本和其副本出现不同(即将这个值认定为噪声),最终会有 25% 的概率认为这是一个缺陷。因为此时稳定版本和其副本值相同,候选版本和稳定版本值不同。因此,Diffy 还会聚合原始区别和噪声,当发现二者出现的概率类似的时候,会认定之前识别出来的缺陷属于误报
4、Diffy 的安装与部署
4.1 拉取代码并构建
前面简单介绍了 Diffy 的作用和原理,了解了 Diffy 介绍 的作用和原理后,可以将 Diffy 工具的源码拉到服务器中:
git clone https://github.com/twitter/diffy.git
代码拉取完成后,进入到 diffy 目录后,使用 ./sbt assembly 进行构建。但需要注意,windows下会构建失败
构建完成后,在 diffy/target/scala-xx/diffy-server.jar 下就能找到可执行 jar 包
其实构建的目的就是为了获取可执行的 jar 包,我这里已经有构建好的,可以直接下载并上传服务器即可直接使用:diffy-server.jar%E4%B8%8B%E8%BD%BD%E5%90%8E%E4%BF%AE%E6%94%B9%E4%B8%80%E4%B8%8B%E6%96%87%E4%BB%B6%E5%90%8D)
4.2 部署 diffy 服务
有 jar 包后,可以运行 jar 包并初始化一些diffy命令:
java -jar diffy-server.jar-candidate=localhost:9992-master.primary=localhost:9990-master.secondary=localhost:9991-service.protocol=http-serviceName=My-Service-proxy.port=:8880-admin.port=:8881-http.port=:8888-rootUrl='localhost:8888'-summary.email=zxxx@xxx.com
相关参数介绍:
| 参数配置 | 含义 |
|---|---|
| java -jar diffy-server.jar | jar包路径进行运行 |
| candidate=localhost:9992 | 待上线版本部署地址,即候选版本 |
| master.primary=localhost:9990 | 已上线版本地址 1,即稳定版本 |
| master.secondary=localhost:9991 | 已上线版本地址 2,即稳定版本副本 |
| service.protocol=http | http 协议或 https |
| serviceName=My-Service | 服务名称 |
| proxy.port=:8880 | 后台输入请求的时候,需要往这个端口上发送 |
| http.port=:8888 | |
| rootUrl=’localhost:8888’ | 这个是jar包运行时,前端的访问地址 |
| allowHttpSideEffects=true | Diffy 考虑到安全性,POST,PUT,DELETE 请求默认忽略,因此该参数为 true 则表示这三种类型请求仍能正常代理发送 |
| summary.email=”xxx@xx” | 对差异发送到指定邮箱 |
| responseMode=primary | 代理服务器是否返回结果,默认 (empty) 无返回,可指定 primary 返回线上版本,secondary、candidate |
