使用robotframework做接口测试5——一个用例中调多个接口

凡是涉及一点点有接口关联的,都可能下一个接口需要上一个接口的某个返回值作为入参,最直接的例子,就是登录依赖。用接口做业务性的测试,也绝对离不开接口依赖的,业务都是一系列接口串联的结果,有时候一个接口操作的结果,也需另外的接口验证,举几个例子,以某个文章的评论用例为例,我们选取几个评论的冒烟用例来看看吧。

  1. 拉取评论列表(list接口)
  2. 增加一条评论(add接口)
  3. 将评论置顶及取消置顶(stick接口)
  4. 删除评论(delete接口)


用例1很简单,仅是个数据读接口没有做写操作,做一些基本的响应校验就OK了,这个接口不在我们的讨论范围。
再看用例2,增加评论是有个写操作的,对于这一操作,如果用手工测试,完整校验点应该是,1)增加评论成功  2)增加的这条评论在评论列表里(且在第一位,考虑到有置顶情况,那就在第2位),所以,这里的最基本的校验点涉及两个接口,第1个接口(add接口)依赖第2个接口(list接口)做校验。事实上,这个评论id还需给其他接口使用,以达到数据清理及重复利用的效果,这个也不在本文的讨论范围。

当然,这些接口,还有个更全局的依赖,用户登录。用户登录的依赖在之前的文章已经有提到过,放在suite setup里是不错的选择:接口登录保持
既然是需要一个用例里面有多个接口,我们希望代码越少越好,最好是一行解决一个接口。这是反向思维,正向的思维是:接口类型固定时,总是有规律可循的,所以当很多很多代码开始重复时,我们要抽取成一个比较通用的关键字,以达到精简用例的效果,用例清晰明了,写起来也简单,扩展容易,维护工作量异常小。这有点像代码重构的思想。

接口测试用一句话概括就是,用什么样的测试数据,测哪个接口,得到的怎样的响应。重点明确了,用例中,接口的基本要素只有1、待测接口  2、待测接口的入参  3、响应数据。一个关键字如果满足了这些要素,也就能达到我们想要的效果。
来看一例:

简写post1.png


在此用例中,mobile_post关键字将一些接口调用的细节全都掩盖掉了,其中包括但不限于:

  • 请求的host及一些固定的参数
  • 接口入参反向update到入参模板里
  • 接口数字签名
  • 目标返回值的分拆及获取

该关键字的必需参数只有1、待测接口名 和 2、待测接口入参,其他一些只做为可选参数,有更多的输入自由,也使得关键字的可重用性更高。然后,一个接口就一行脚本,断言在关键字外做,也是为了提高写用例的灵活性。实践证明,使用这个关键字后,写用例速度明显提高了。该关键字中用到的更底层关键字,也尽量用rf的关键字在写,rf的日志打印比较好,遇到问题方便日志追踪。
 
 
这里重点讲一下接口的入参模板:
1、为什么要有入参模板
百度结果中有好多告诉你怎么用rf做接口测试的文章,如何创建session,如何用create dictionary关键字构建测试数据,如何传header,如何做一个post接口,如何做一个get接口。——那只是个demo
我们做自动化时是在做工程,不是在做demo,也就是那些解释性的脚本,底层一步一步怎么实现的(header怎么传,data怎么拼接,该用post还是get),已经不再是重点,我们更应该关注的,是用例本身,怎么写用例能更好的覆盖到验证点,怎么处理测试数据,怎么写好可维护性的用例,怎么去组织好用例结构,套件结构,工程结构,怎么让用例有更好的环境(测试,预发,生产)移植性。
扯远了,回到入参模板。实际中,单单一个接口的入参就多得不敢想象,十几个,或更多,某个用例中这十几个入参实际起作用的也许就3-4个。有些接口其实也不止一层json那么简单,也有某个字段有多层结构的。这个时候,最好是有个模板,模板大概长这样:
           接口A:{key1:value1, key2:value2}   #接口A及其入参
           接口B:{key3:value3, key4:value4, key5:value5, key6:value6}
           接口C:{key7:value7, key8:{Key81:value81}, key9:[value91, value92, value93]}
           ...
 2、入参模板rf中怎么实现

参考了一些其他做接口测试的同仁,有用数据库实现的,也有用初始化配置文件的。rf在这方面考虑还是蛮齐全,我用的是py变量文件vars.py,当配置文件用,另外可能还需要有一个辅助的py关键字文件common.py。

1)大致长这样的vars.py

MOBILE_DEFAULT_VALUE={
        #comment
        "comment.add":{"v":"1.0","data":{"articleid":"1","content":u"大盘啥时候能好起来我就给好评","targetid":"","commentid":"",,"uid":"1"}}, #增加文章评论接口
        "comment.list":{"v":"2.0","data":{"articleid":"","cursor":"-1","count":"20"}},  #获取文章评论列表
        "comment.delete":{"v":"1.0","data":{"commentid":"","uid":""}}#删除评论
}

2)大致长这样的common.py

# -*- coding:utf-8 -*-
import vars

def mobile_paras(apiName,dataStr='{}'):
    '''
    参数:待测接口名apiName  待测接口入参 dataStr
    示例: ${return} | mobile_paras | user/sms | {"phone":"66666666"}
    返回:接口版本号 及最终入参
    '''
    try:
        datadict = vars.MOBILE_DEFAULT_VALUE[apiName]['data']
        apiVersion = vars.MOBILE_DEFAULT_VALUE[apiName]['v']
    except KeyError:
        print  u"不存在的api名,请重新输入"   
		 
    if dataStr == '':
        dataStr = '{}'

    dataNew = eval(dataStr)
    datadictCopy = datadict.copy()
    datadictCopy.update(dataNew)#这句是关键,把数据update到模板取到的data中去
    
    return [apiVersion,datadictCopy]

分离变量文件和关键字文件是rf的规定,也是个好的编码习惯,以后vars.py中还要扩展其他更多更多的变量,当然common.py中也不可避免增加一些rf不擅长但python擅长处理的关键字。

3)大致长这样的mobile_post关键字:
最后,用一个rf的关键字,把一些关键数据组一组,该签名的签名,该登录的登录,该返回的返回:

5-2.png


再回到第1张图,待测接口comment.add,目标待传参数in_data为{"articleid":"3215","content":"大盘啥时候能好起来我就给好评","targetid":"","commentid":"","uid":"101123"},用例传参{"articleid":"3215","uid":"101123"},其他参数在模板中已默认,实际传参如目标待传。
 
4)结构:
 vars.py及common.py放同一级目录,以如下方式导入含有mobile_post的resource文件中

5-3导入结构.png


以上,仅提供思路。有些同学的接口入参及调用都很简单,3行内可以搞定一个接口,也可不必做得这么麻烦。在工程化的道路上,只有实践出来的路才是最好的路。

posted @ 2018-04-10 10:02  澄心  阅读(2032)  评论(2编辑  收藏  举报