7、大型项目的接口自动化实践记录----数据分离升级版
一、常规数据分离
上一篇,实现了订单新增接口的请求,这块的核心业务case200+,因此要做下数据分离,先提取下方法:
1、新建resource:订单新增接口.txt,在resource下新建关键字订单新增接口、变量${URI},${URI}值为订单新增接口对应的URI,即/c/contractsign/addcontract
2、订单新增接口
如上图,提取关键字,后面case数据,只需要维护${port} | ${username} | ${password} | ${data}
因为登录属于前置条件,因此放到setup中,订单新增接口只保留它自己的内容
如下图,改完后,在case层,则只需要维护登录的信息、data
PS:登录方法中,在最后需要加,这样case中cookies才可以用
因此常规数据分离如下图:
完成了数据分离,则开始专注维护测试数据
维护下来,发现工作量很大(主要是其中data部分,可见上图滚动条),而且很容易出错。因为其中很多字段关联性强,且有值为json串,如果要保证正确性,则需要通过前端操作,抓包获取数据,这样工作量巨大。以一个case10分钟为例,需要超过2000+分钟,这只是系统的一个模块而已,想想功能要有所变动,增加字段,那维护量就太大了。
二、数据分离升级版----需要解决的问题
头脑风暴:每次新功能或者功能变动,都会有对应的手工测试,而手工测试完,在DB中都会留下对应的测试数据。如果可以用特定规则,获取到这些数据,在case层只需要维护如下内容,那么数据的维护工作就很低了。
数据库名:数据来源库
数据主键:要取的数据的主键
端口号:要在哪个环境做接口请求
方案思考:
1、封装对应的数据获取逻辑,根据数据主键、来源库获取对应的数据
2、处理获取到的数据中的唯一值、特殊值等
3、最后根据接口字段与DB字段的映射关系,获取到对应的data
如下图:
这样在case层则只需要维护用例、数据主键、来源库,就可以获取到对应的data,手工测试过的数据,就可以快速复用了。
需要解决:
1、从DB获取数据
2、功能对应的数据库表整理
3、数据获取后,一些字段的值需要修改
4、接口字段与DB字段的映射
着手去解决:
1、从DB获取数据:
1)先打通数据库
在suite文件处,先导入库DatabaseLibrary、Collections、String
实现连接数据库,查询:
①连接数据库:Connect To Database Using Custom Params
Driver=对应装的ODBC版本
Server=数据库地址(一般是数据库服务器IP)
Port=端口号
Database=要连接的数据库name
User=用户名
Password=密码
②查询:Query
③打印查询结果:log ${data}
可以在日志可以看到成功获取到了数据,数据格式为由元组组成的list:[(),()]
2)封装对应方法
①连接数据库:
假设常用的环境对应的数据库有三个,分别为DB1、DB2、DB3,每个库都有对应的用户名密码等信息,则配置如图10,变量名以num结尾,第一个库的信息为0,第二个为1……。
连接数据库的方法,根据传入的库名,设置变量${num},然后根据${num}连接对应的数据库。
②查询数据:
上面看到,用Query可以查询到对应的数据,但是格式是元祖组成的list,不太方便后面的使用,如果数据是字段名+value的键值对,即[dict,dict,……],则会比较方便使用,因此我们再做下封装。
A、首先根据查询语句获取keys(字段名)
B、然后根据查询语句获取keys及datas
C、再然后keys、values拼接成dict
PS:有简单的写法${dict_back} Evaluate dict(zip(${keys},${values})),但是因为我们的数据会有特殊值,该写法会出错,因此没有用。
D、接着用获取的keys、datas组成dicts_list
E、最后根据查询语句,获取数据dict集,拼接成dicts_list
好处:后面使用方便
缺点:性能变差(因此大数据时不使用)
2、功能对应的数据库表整理
考虑预发布环境操作的频率会较低,因此在预发布环境开放SQL日志
然后在linux服务器上,对应的目录下,加一个脚本,内容如下,其中mysql-bin.index为二进制日志汇总
脚本功能:根据起止时间,过滤出insert、update、delete开头的语句,其中mysql-bin.index为日志汇总,这样用户在预发布环境操作后,可以根据起止时间,过滤出对应的SQL语句
为了获取SQL执行语句,还要专门上linux服务器执行命令,这样比较麻烦,因此在RF上去实现下:
导入SSHLibrary
通过SSH连接到linux服务器,入参为起止时间,执行linux服务器上的脚本,更新sqllog文件
接着把linux服务器上,对应的sqllog文件下载到本地指定路径
PS:Get Tables是自己封装的方法,作用是再根据下载下来的文件,过滤出对应的表名并去重。
3、修改字段的值
举个栗子,假设一个单据对应多条明细,单据id为100,我们通过方法”根据查询语句,获取数据dict集,拼接成dicts_list“ + ”SELECT * FROM 明细表 WHERE parentid=100“,查询到结果如下:
[{u'name': u'test1', u'parentid': u'100'}, {u'name': u'test2', u'parentid': u'100'}]
其中parentid为明细对应的主表id,我们在RF这边模拟构造下这个数据
当我们从DB获取到主表及明细表的数据,当做测试数据使用时,那么会发现,新增主表数据的时候,有新id生成,假设为101,那么新增明细的时候,对应的parentid需要改成101。可以通过for循环遍历list,把其中的parentid改掉,如下图。
结果如下,可以看到parentid都变成101了。
4、接口字段与DB字段的映射
映射关系如上图,其中${data_all}、${current_data_all}为前面dicts_list中的dict,因此如${data_all['id']}可以取到对应的id值,传给接口的id字段。
三、数据分离升级版----订单接口实现
我们以逆推的方式,去看这个过程实现
1、首先新建合同和订单新签目录,在目录下新建DB与接口映射关系Resource,在该Resource下,放图9中的func3,根据映射关系、数据,获取data。
1)在Resource下新建方法,获取cdn订单新增data。
方法内容如下,新建${data},把接口抓到的所需要的入参都add上。
2)观察字段来源于哪张表的字段,发现分别来源于contract、paycls、pay表,还有些特殊字段如cdnitemjson,它的值是一个json串,相当于子data串,因为这层做的是data这层的映射,因此先不管它。
假设我们已经取到了对应几张表的data及几个json串,并且已经处理过,则映射关系如下图:
3)同样的,新建获取对应的appditemjson、cdnitemjson、speedjson
与主data不一样的是,这些json串,数量可能为0~N,因此入参为dicts_list,映射关系写法如下图,在for循环中做对应的赋值(这里只写两个字段做下说明)。
2、新建Resource:DATA_来源,在下面放图9中的func1,用于从DB获取数据
1)新建方法,获取对应的数据
2)因为我们要查的数据不多,因此直接用了select *,主data信息都是一条,返回的是dict,所以返回list[0]
对应的json串数据,数据可能性0~N条,因此返回dicts_list
3、新建Resource:DATA_处理,在下面放图9中的func2,前面获取到的数据,还不能直接使用,需要对其中的一些特殊字段进行处理。
1)新建方法,处理对应的数据
2)下图为json的字段处理举例,其中接口请求中字段为id,但是DB中则不是,act字段为固定值,有的字段可能会是随机数等。
4、新建Resource:操作步骤_DATA,引用前面3个Resource
1)在目录下,新建方法订单新增data,实现获取、处理、映射成接口可用data的过程
2)方法内容如下,将前面的过程串联起来,发现我们只需要传数据主键,就可以获取到对应的data了。
5、再跟前面的Action等关联上,新建Resource:操作步骤,引用操作步骤_DATA。
1)新增方法订单新增,即操作步骤的ACTION
6、新建Resource:订单新增FLOW,引用”操作步骤“
1)新增方法订单新增FLOW,连接数据库,执行操作步骤,实际结果与预期结果对比
7、再新建suite,引用订单新增FLOW,在suite下新建case,则实现了图8中所期望的。
作者:慢慢走的测试
出处:https://www.cnblogs.com/walkingtester/
交流群:636090586(备注博客园)
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果喜欢我的文章,请关注我的公众号