为了更好的演示接口测试,笔者部署了一个Redmine服务,本系列文章均以该系统作为被测试服务,当然你也可以自己搭建一个redmine系统,可以利用docker快速部署:https://hub.docker.com/_/redmine
1. 接口文档
接口文档是进行接口测试的必要输入,一份好的接口文档笔者认为需要包含以下要素:
- 接口的鉴权方法
- 接口的调用时序
- 接口的必传、可选参数,以及各参数的语义
- 接口响应报文,以及相关字段语义
- 接口请求、响应报文demo
因为我这里使用了redmine,其官方接口文档地址如下:https://www.redmine.org/projects/redmine/wiki/Rest_api
除了传统的手写接口文档,目前还有一些好用的接口文档框架,比如著名的Swagger: https://swagger.io/ 以及国内的YApi: https://yapi.ymfe.org
如果你所在的团队、部门准备开始着手接口自动化测试,而开发又无法提供接口文档,建议尽快跟开发负责人协商
2. 理解接口行为
我们首先确定用来练习的接口:https://www.redmine.org/projects/redmine/wiki/Rest_Issues#Listing-issues
该接口返回满足匹配条件的issue列表,所有参数都可以认为是可选参数;另外redmine的接口响应报文提供两种格式:json以及xml,
所以最简单的调用方式是/issues.json
2.1 鉴权方式
在postman上调用/issue.json
看上去没有问题,但是返回的数据是空的:
- 有可能是的确不存在任何issue,自然也就返回了空的数据
- 调用方权限问题:没有权限获取资源对象
经确认响应接口为空属于上面第二点原因,未通过服务器鉴权,会认为调用方会匿名用户,无权限。
回到文档的鉴权章节:https://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication ,我们可以看到redmine提供三种鉴权方式:
- 把用户key作为query string传入,参数名为
key
- 将用户名、密码以HTTP Basic authentication的方式带上
- 把用户key以http请求头的方式带入,参数名为
X-Redmine-API-Key
我这里选用第三种方式,使用postman验证下响应报文:
跟第一次调用相比,这次不再返回一个空数据了,而是真实返回了该用户所能查看到的所有issue。
2.2 可选参数
这次我们再尝试下传入可选参数,/issue.json
的可选参数相当多,我这里假设调用目标为:返回项目1下的所有issue,响应结果按照issue创建时间升序排列
3. 接口封装
基于postman的三次调试,我们其实已经基本了解该接口的行为:
- 需要鉴权
- 无必传参数
- 响应结果视作
json
,xml
处理相对麻烦
所以我们可以着手第一版封装:
def list_issues(api_key, **kwargs):
"""按条件查询issue"""
return requests.get("http://redmine.xuh.me/issues.json", params=kwargs, headers={"X-Redmine-API-Key": api_key}).text
然后调试代码:
>>> print(list_issues("490592ea4e46348df29828edd597acbfdc5ebb4a"))
{"issues":[{"id":2,"project":{"id":1,"name":"接口测试实战"},"tracker":{"id":3,"name":"支持"},"status":{"id":1,"name":"新建"},"p ......
不出意外的话,你在控制台能看到跟postman一样的响应结果。
但是这样的封装太过于简单,思考以下问题:
- redmine是个通用程序,或者被测服务可能处于不同环境(开发/测试/生产),把服务入口地址写死是否合理?
api_key
其实与接口逻辑无关,而且每个参数都需带入,是否应该有更合理的传入方式?list_issue
返回了json格式的字符串,提取相关字段并不方便,更合理的处理方式是什么?requests.Session
在哪?为何不见踪影