Python接口测试实战4 - 封装redmine接口

为了更好的演示接口测试,笔者部署了一个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看上去没有问题,但是返回的数据是空的:

  1. 有可能是的确不存在任何issue,自然也就返回了空的数据
  2. 调用方权限问题:没有权限获取资源对象

经确认响应接口为空属于上面第二点原因,未通过服务器鉴权,会认为调用方会匿名用户,无权限。

回到文档的鉴权章节: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的三次调试,我们其实已经基本了解该接口的行为:

  • 需要鉴权
  • 无必传参数
  • 响应结果视作jsonxml处理相对麻烦

所以我们可以着手第一版封装:

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在哪?为何不见踪影