摘要:公司某个单证查询接口完成不同Appid、不同单证、不同业务类型的业务逻辑覆盖至少取3个Appid ,同时对应相同的业务和单证(10种),由于业务上还存在查不到数据和查得到数据的分支流程 ,因此总共需3*10*2(查得到、查不到) =60条用例。
一、背景
公司某个单证查询接口完成不同Appid、不同单证、不同业务类型的业务逻辑覆盖至少取3个Appid ,同时对应相同的业务和单证(10种),由于业务上还存在查不到数据和查得到数据的分支流程 ,因此总共需3*10*2(查得到、查不到) =60条用例。
并且单证查询接口仅3个月内就进行了6个版本的变更,一个接口有如此高的重用度,手动测试必然花费的时间长,也繁琐;需要的精力和时间都是巨大的。因此,通过自动化手段解决手动测试带来的各种成本,是必须解决的问题。
二、实践
1、问题点描述
实现自动化需要解决以下几个问题点:
1.自动化工具的选用
2.工具的自动化方案具体实现:
a.接口请求数据需加密
b.数据驱动:参数化、模块化,代码不冗余
c.数据驱动:关联数据的提取和使用
d.数据断言:实现不同Appid的业务结果校验
2、思路和方法
Jmeter的取样器、断言、监听器可以完成一次完整的发起请求、验证结果、记录结果的全过程,并且通过UI界面直接操作入手容易;另外,它不仅支持单线程的请求,而且对多线程的处理也非常成熟。因此,十分适合既要接口测试又要进行压测的测试项目。
除此外,Jmeter可以调用外部jar包,也提供了许多内置函数,可以实现丰富的个性化测试需求,扩展性好。也十分适合请求数据加密的情况。
在Jmeter脚本实现上,单个请求发起请求、验证结果、记录结果的整个流程脚本实现非常容易,但测试工作的中心是数据,而不是测试脚本。如何实现单证查询接口这一测试背景下的大批量数据驱动呢?
A、需要进一步分别实现分组逻辑下的数据驱动和校验:【查不到线程组】
BeanShell PreProcessor是在取样器执行之前的处理元件,它可以调用外部加密包,也可以对数据获取进行参数化,以及支持所有逻辑关系的编程实现。
2.代码和变量分离,使用CSV Data Set Config和User Defined Variable 实现数据的参数化:
由于测试数据量较多,采用外部文件的方式通过CSV Data Set Config获取所有业务类型和单证类型;另外,由于6个Appid都对应同样的业务、单证。避免数据冗余,因此Appid需单独进行存放。同时,这种情况下为了减少代码的冗余,可以循环控制器的使用,因此由User Defined Variable配置元件来存放各个appid。
3.使用循环控制器+User Defined Variable实现所有Appid 的查询接口循环遍历:
基于方法二:减少代码冗余的原因,通过user defined variable设置的变量名带索引,再通过循环控制器控制索引区间控制Appid范围。
4.用Jmeter内置函数、变量获得系统时间、响应结果:
Jmeter提供了一些常用的内置函数和内置的一些系统变量。比如时间函数,可以获取当前时间,在此场景下,不需要另外编码,可以让实现更轻松。
5.用JSR223 断言来实现不同Appid的业务结果校验:
一个强大的自动化测试工具必然包括了测试结果验证,为了在一组请求里,能够根据不同Appid进行结果验证,只能依靠编码判断实现。JSR223 断言可以实现了编码功能。
【查得到】线程组的脚本架构基本与【查不到】线程组一致,但【查得到】线程组需要额外解决问题:如何获取到已经存在于系统中的数据,并发起请求:
方案一:通过Jdbc取数据库中的旧数据 。
因为后台表设计按业务分表,和脚本按Appid区分的逻辑相悖,实现起来会非常复杂。
方案二:直接发送实时合成请求,发送逻辑更简单,但查询和发送的保单存在一对一的关联关系,因此只要解决:1需要用正则表达式提取器完成关联数据的获取以及使用2使用循环控制器+计数器实现循环遍历进行下一个:生成PDF请求3.断言上,同一个PDF文件名,需要能够判断出是新生成的PDF还是之前的PDF即可。
1.2问题实现都比较容易,第三点问题:观察响应结果后,发现 数据路径中里包含了生成时间,只要制单接口生成时间和发送查询生成时间不一致就能断定是新生成的PDF。因此,从方案二角度实现更为简单:
6. 使用循环控制器+计数器实现循环遍历生成PDF请求:
For each 循环控制器实现每轮each中的变量都取同一组数据,因此生成的保单号有一样的情况,验证将不够严谨。此时可以加入计数器来使得保单号唯一。
7.用正则表达式提取器完成关联数据的获取以及使用:
Jmeter提供多种提取器,如Json提取器,边界提取器等。但查询接口响应的数据路径较为复杂,且存在多个类似的符号边界,如下图响应结果里需要获得PDF文件名:
故只能用正则表达式提取器的来取值,因为返回结果中又存在重复数据,故非贪婪匹配模式来取值。
3、实践方案
一.【查不到】线程组
(一)使用CSV Data Set Config和User Defined Variable 实现数据的存储。
(二)用BeansShell PreProcessor来处理请求数据加密、参数化:
BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;可通过vars.get 、vars.put 进行Jmeter变量与Beanshell变量间的转换,如下图:每次请求获取参数化变量:document和job,并依次替换请求body,再调用加密方法对body进行加密,最后转换 为Jmeter变量返回给Jmeter工具以后后续的http请求使用:
(三)用BeansShell PreProcessor来处理逻辑关系的判断 :
不同Appid对应不同的秘钥,需要通过BeanShell完成Appid与秘钥间的一对一匹配。
(四)使用循环控制器+User Defined Variable实现循环遍历查询接口:如下设置索引值,分别对应appid_1,appid_2,appid_3三个变量,并且实现了每次循环,不同Appid获取同一组的业务类型和单证,此时线程组根据业务类型和单证的总数设置迭代数为10,即可保证数据的完全遍历。
(五)用Jmeter内置函数获得系统当前时间,以满足查询的单证号在系统中不存在:
用Jmeter内置变量获得系统的响应数据:
(六)用JSR223 断言来实现不同Appid的业务结果校验:
JSR223 断言同样可以使用Java的语法,因此使用Java的正则判断方法,来判断实现:判断是否生成pdf,其他情况提示数据不存在。
(七)使用循环控制器+计数器实现循环遍历生成PDF请求:
在请求前添加Counter计数器,并设置为局部变量来满足每个请求的单证号的变化,保证数据唯一。
(八)用正则表达式提取器完成关联数据的获取以及使用:
提取生成PDF的文件名作为查询请求的参数,以及断言的变量。
提取生成时间作为断言的变量:
(九)由于使用Jmeter工具进行实时制单和查询接口制单的效率快,他们的系统时间可能一样。故在两请求间添加了延迟请求器:1ms 以避免以上情况:
4、实施成果
查看结果树监听器可以看到测试执行的结果:当与预期相符情况下不会标红,与预期不符的情况下标红。如图,由于重新制单时调用模板错误,响应的数据与预期不符,故标红突出显示:
三、总结
60个用例,自动化脚本执行时间约15分钟左右,而若手工测试执行+验证按2分钟来算,则需至少120分钟以上。
Jmeter的可扩展性,在个性化需求、以及复杂的逻辑判断的实现上相当方便。并且在脚本重用度高的情况下,Jmeter自动化脚本不仅可以协助完成测试任务的执行,也可以避免人为疏忽带来的Bug遗漏,同时也提高了测试效率。可以做到提质增效。
文末了,我邀请你进入我们的软件测试学习交流群,大家可以一起探讨交流软件测试,共同学习软件测试技术、面试等软件测试方方面面,了解测试行业的最新趋势,助你快速进阶Python自动化测试/测试开发,稳住当前职位同时走向高薪之路。
来源:小鱼科技频道