接口测试 搞定接口测试变态要求:海量接口返回值对比验证

zyanycall · 2018年08月01日 · 最后由 小肉包 回复于 2019年10月29日 · 7608 次阅读
本帖已被设为精华帖!

上半年我给自己挖了个坑,说海量接口返回值比对是接口测试的核心要求之一,这次来说一下我是怎么做的。
做一下必要的铺垫,也顺带说一下测试的工作方式,各位看着高兴最好。
每个公司遇到的需求及问题都是不同的,大家还要因地制宜。

背景

公司最近搞了一个新项目,既实现了新的代码同时也复用了老的环境。
而复用老环境时,某核心开发因为看不下去老的代码(确实)太烂,打算借此机会重构老代码,一波上线。

开发的测试要求

希望老系统代码重构后,接口返回值没有变化。
涉及接口超过 100 个,几乎都是读接口。
回归测试强度,即核心业务逻辑没有改动,是代码结构的变动。仅观察返回值结构等是否一样即可。
可以提供原有环境及新环境,便于对比。
时间紧迫,要 1 天内搞定。
接口数量太多,影响较大,测试要认真对待。

测试的疑问

为什么现在才提重构老代码的事儿。
老代码重构和新代码上线不能混为一谈,新代码上线是雪中送炭,老代码重构是锦上添花。
无法理解为什么要一波上线,老代码重构可以慢慢搞,没必要一起上。
时间太紧迫。
接口数量太多,能否缩减范围。

开发的答复

重构老代码是某核心开发自己搞的,确实不在需求之中。
老代码重构势在必行,实在看不下去了,并且新代码上线后压力会大,担心有问题。
其实之前已经有部分重构代码上线了,但线上出了问题,所以后面的涉及重构的都需要验证测试。
新老代码混合程度较高,单独摘除老代码重构成本不小,时间消耗上摘除和一起上线差不多(反正已经上了一部分了)。
开发较自信(线上打脸了才想起来测试?),到现在还是很自信,重构没啥问题。
所以之前没测试重构,说重构了也担心不允许,那这些老代码会一直烂下去。
测试帮帮忙,相信你。

我的思考

我非常理解核心开发重构代码的动机。
这是个展现测试价值的好机会,如果你们开发能搞定就不会来找我了。
开发没办法搞定也没时间搞定了(线上 bug 修改等事情很多),时间紧迫。

此时此刻只有我才能搞定这件事儿(自带特效字带背景音乐自带慢动作)。

我的底气

接口测试用例数据,这个是接口测试独有的,也是让这一切可执行的基础。
我开发的各种工具。

完成任务的方式

  1. 手工执行 100 多个接口,然后新老环境各执行一遍,之后使用 beyond compare 比对一遍。(这不是让开发看笑话吗?也可能开发的预期就是这样,所以没时间搞)。
  2. 将任务 1 分工下去,比如测试方出 5 个人,开发出 5 个人,每人 10 多个接口,手工执行,比对,汇总结果。(需要牵头人,体现领导才能?但是任务会上升,牵头人未必是我)。
  3. 自动化执行 100 多个接口,然后手工拷贝每个接口的返回值,两次自动化后 beyond compare 比对。 存在的问题: 1) 接口返回值非常长,即便是软件比对,细节也看不清,返回值需要格式化。 2) 拷贝结果要执行 100 多次,要执行两遍,非常非常繁琐麻烦和累。如果一遍比对不成功那画面太美。 3) 如何有效执行 100 个多接口。
  4. 必须自动化执行。

自动化执行的方式

  1. 完全代码实现,比如测试用例数据保存在数据库中,代码首先读取数据库,然后依次执行每个接口,将所有的返回值汇总并格式化输出成文档,一键拷贝比对即可。
  2. Jmeter + Ant 再加工实现,读取数据库使用 beanshell,依次执行每个接口使用 Jmeter 自带功能即可,结合 Ant 产生测试报告文件就是测试结果文档。

  3. 完全代码实现是可行的,我也实现了,但不是为了这种比对场景做的,是为了边界测试(后续可能分享挖坑)。

  4. Jmeter + Ant 需要再加工,比如测试报告中结果的格式化,测试报告的文档拷贝的一键执行,我实现了这些,今天讲这些。

  5. Jmeter + Ant 在此次场景下,是最方便的,因为我之前实现了很多功能,就为了这种硬仗准备的。

Jmeter + Ant 测试工具的二次开发

上面已经简述了任务要完成需要做的,再汇总一下:

  1. Jmeter 脚本要读取数据库,获得这 100 多个接口的接口测试用例数据,然后可以脚本执行。这种执行可以切换新老环境,达到新老环境每个都执行一遍的基本要求。
  2. Ant 运行 Jmeter 脚本后,会生成 html 格式的测试报告,但是需要将测试报告中的返回值格式化(JSON 格式化)。
  3. html 格式的测试报告,要有一键获取所有格式化的测试结果的功能,这样才能高效的复制出来这 100 多个接口的返回结果,才能比对。

Jmeter 脚本如何读取数据库并执行所需要的用例

这里就口述一下了,简单贴图,毕竟详述太费劲。

  1. 通过 SQL 语句,筛选获取测试用例的主键 ID 集合,比如 (100,101,102,103,104),同时获取数量,比如总数为 5,都保存为自定义变量。
  2. 使用 Jmeter 的循环控制器,循环的次数就是上面第一步获取的数量,循环 5 次。

  3. 在每个循环中,从主键 ID 集合中从头拿 ID,比如拿到 100 这个 ID,记录数组下标为 0,保存数组下标为自定义变量,根据 100 这个 ID 获取的所有的接口测试数据定义为自定义变量。

  4. 根据上面第三步获得的数据,来执行 HTTP Sampler,真正的发出请求。

html 格式的测试报告如何格式化

我改造的是最流行的 jmeter.results.shanhe.me.xsl 结果模板。
这个已经放到 CSDN 下载上去了,我上传的,代码我也就不详细贴了,毕竟说起来很麻烦,说一下当时解决的思路。

  1. xsl 我找资料查了下,是一种生成 html 的模板,里面包含各种函数逻辑,是可以同时有 js 代码和 html 标签结构的。
  2. 既然是 js 和 html 标签,那么我需要在网上找一个格式化 JSON 的 js 代码,将其嵌入到这个模板中就好。
  3. 我认为,hmtl 文档中保存的是非格式化的数据,左侧超链接单击时,触发格式化 js 代码可行,这样 html 文件最小。
  4. 难点是,如何唯一标识每一个返回值,唯一标识后,才能单击哪个格式化哪个,才能找到数据。

然后我都搞定了。

如何一键获取所有格式化的测试结果

我继续加工上面的 jmeter.results.shanhe.me.xsl 结果模板。
思路:

  1. 找到一个触发条件,循环所有的上面已经格式化好的结果集合,找地方都存起来。
  2. 最好是一键下载,比如我打开 html 文件,点一下,提示我下载,最方便。可惜,由于浏览器出于对数据的保护,不允许下载,执行这种操作,生成文本都不允许。
  3. 使用 console.log 方式,将这些结果都打印到日志中,浏览器开发者模式下,全选拷贝出来,用于比对。

结尾

我当然解决了测试任务,并且开发再次被打脸,重构的问题还是很多的。
收到了表扬信。

讨论一下 Jmeter + Ant 和完全自己开发的优势

  1. Jmeter + Ant 可以再 + Jenkins ,这是持续集成,完全自己开发要做到这些,工作量还是有不少的。
  2. Jmeter + Ant 已经有了,已经满足了很多要求,没必要再造轮子了。
  3. Jmeter + Ant 最核心的 Jmeter,功能太丰富了,比如正则表达式,自定义变量,参数化,性能测试,定时执行等等。 这基本满足所有复杂的接口测试要求,自开发这些工具真的比不了。
  4. 接口返回值的 mock,不在此讨论之列。
共收到 46 条回复 时间 点赞

没有单元测试保证的重构都是耍流氓,开发重构之前需要学习一下如何编写单元测试(或许你身边有一堆不知道如何编写单元测试)。

楼主用 jmeter 处理有点复杂,如果仅检查返回码,一个连数据库的函数 + 一个循环便可解决问题。

JS 应该有集成好的 JsonSchema 可以直接用吧

beyond compare 有命令行的执行方式,输出的报告也很直观

Twitter :Diffy 是否可以满足啊

既然是海量,那么
男儿何不带 mapping,直接测试 DB 层?
接口测试就那么好玩吗……

乾行 回复

不仅仅是测试返回码啊~返回值的格式,甚至大小写匹配,返回值的 key value 都要一致的。

BugaoxingXXX 回复

这个地方主要是对比测试,两个环境海量接口返回值的对比测试。
Json Schema 明显是没做的……你的建议很好,不过很难推行。

群主是狗 回复

beyond compare 命令行没用过, 能把 JSON 格式化后再对比吗?

lovoro 回复

不了解这么高端的工具。

槽神 回复

接口返回值可以包含多个表的数据,再说接口可能有缓存的,都不调用 DB 的数据,直接测试数据库是不行的。

看了看 diffy 介绍,感觉可以用来解决你的问题。

丁老九 回复

diffy 是个好工具啊,界面也不错。应该可以搞定我的问题,即便搞不定二次开发的工作量也比较小,主要是这测试结果是在线的很赞。

zyanycall 回复

我比较感兴趣的是重构如何影响字段的大小写了?

zyanycall 回复

此外大小写是否一样在 for 循环加上一个断言便可解决

可以看下我这篇文章,早就写好你想要的比对了
接口测试 [JsonSchema] 关于接口测试 Json 格式比对核心算法实现 (Java 版) https://testerhome.com/topics/9252

CC 回复

不错,学习了。

乾行 回复

你的一个连数据库的函数 + 一个循环 再加上 @hu_qingen 的接口测试 [JsonSchema] 关于接口测试 Json 格式比对核心算法实现 (Java 版) 这应该就是你写的 “一个断言” 的完整实现。

至于重构怎么改变大小写了,你很感兴趣……可能测试的工作就是这样吧,面对的是各种各样的问题。
没别的意思,我觉得我的这篇至少引发了你对解决问题的思考,并且你也感兴趣了,我觉得就很好。

思寒_seveniruby 将本帖设为了精华贴 08月02日 15:49

twitter 的 diffy 其实是可以的。

CC 回复

schema 还不行,schema 校验只是校验目标字段的范围,还是有点笼统,使用 diffy 这类的方案是最好的。楼主写的也不错

谢谢版主肯定。

zyanycall 回复

1、在 python、node.js 中 json 对比真实的就是一个断言实现,Java 用得少,但我相信已有开源的已实现对比的 jar 包;
2、重构代码过程中开发将请求参数、响应结果的大小写修改了,我只是对这个开发表示佩服。

我去看下,😀

返回的断言处理我这边分为 第一是验证长度&检查几层的 json,长度可以判断是否是有效的和是否是失效的。检查几层在于第 n 层 value 检查是不是字典,第 n-1 层一层层递归检查。
第二个是验证参数 key 是否包含和 value 是否在包含。用封装的断言库。

zyanycall 回复

你可以自己格式化 json 之后,使用 beyond compare 对比

群主是狗 回复

好的。我文中就是这么做的。

自己用 python 做了个简单的接口验证,get/post 请求,返回结果检查,感觉适合大批量运行。jmeter 只用过性能测试,配置参数循环还是挺方便的。

请问 diffy 有相关的实战使用经验文档吗?

想请问下楼主,返回的数据进行对比验证前是怎么做 json 排序的啊?

使用 mocha,一个 for 循环可以搞定,json 对比字段是由 chai 内部实现的,可以不用关注。
参见:接口测试过程中如何快速进行 diff 测试?

乾行 回复

这个回答做到了:
talk is cheap show me the code.
这套代码工具,可以解决读接口的比对问题,也是我文中所面对的问题。
当然我的 Jmeter+Ant 还是有其优势的:

  1. 接口测试请求链接数据不是数据库/文本等等已经保存好的,需要新创建测试数据。
  2. 请求和请求之间存在数据关联。即和上面第一种情况结合起来。

至少这两种情况,Jmeter 还是比较方便的。
我不展开了,我相信 python/node.js 能做到。

zyanycall 回复

此外,进行接口串联,代码实现也比 jmeter 快与高效,周末有时间再分享

乾行 回复

有你分享的时间,我 Jmeter 都干完活了……行了大兄弟,别在我这掰扯这些了。
我文中写的那么多 Jmeter 的优点看来在你眼里都是 P 啊……“Jmeter,功能太丰富了,比如正则表达式,自定义变量,参数化,性能测试,定时执行等等。 这基本满足所有复杂的接口测试要求,自开发这些工具真的比不了。”
我期待你在 github 上的开源。

其实还可以用正则提取器因为 json 返回的格式都是有规则的,然后把提取的结果放入 ArrayList 最后通过遍历提取出每个 Key 然后进行对比,另外介绍个插件 jmeter 里有个插件 jp@gc - JSON Format Post Processor 可以把格式化 json 接口返回的数据

乾行 回复

好的,谢谢你。我去看看

你好, 请问你对比的是新老接口的返回结果么? 如果是的话,为什么增加数据库的数据获取? 如果不是对比新老接口返回值,是对比返回结果和数据库中 预期返回结果的话,那么每一个接口虽然都是读,但是读的条件逻辑会不一样,那么数据准备这块也会很麻烦,怎么能一下子完成 100 多个呢?

dyy 回复

你好,是接口请求的内容保存在数据库里,所以才需要读数据库。
并不是接口返回的预期值保存在数据库中。

写个爬虫脚本,对新老两个接口进行爬虫,然后用 python 的对比函数处理结果,以前我就是这么干的😂

我最近也接到这样的测试了,还没不知道怎么弄

我数据量有百万。。需要取样来 diff 新老接口的 response 。 我用的是 python 直接访问数据库,然后多线程执行 diff

mark 一下你的方法

仅楼主可见

👍 ,谢谢分享。

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44
simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08

已经 找到 谢谢

我也做了一次,用的 python 个内置库 difflib,可以直接对比生成 html 报告,还有相似度

你好,html 模板能不能发下,参考下

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册