1. 什么是接口测试?

要谈接口测试,先要清楚什么是接口,接口即通常所说的API(Application Programming Interface,应用程序接口)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。 用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问原码,或理解内部工作机制的细节(接口定义来源于百度百科)。

艾玛,太拗口了,还是直接说人话,接口就是将一些复杂的操作封装起来方便其他程序调用,调用的形式可以是本地函数,也可以是网络请求,而我们通常所讲的接口测试大都是基于http协议的api接口,因此本文重点针对http协议的api接口测试进行讲述。

2. 接口请求模型

下图中的门禁,可以理解为接口,用户刷门禁卡的过程可以理解为请求接口的过程,假设用户持有两张卡,一张是“open卡”、一张是“close卡”,当用户刷“open卡”时,相当于给接口参数p传递参数值“open”,此时门禁控制开门,当用户刷“close卡”时,门禁控制关门。

请求模型

3. 接口URL

相信通过上面的栗子,你已经明白接口是怎么一回事了,接下来一起来理解HTTP的URL是怎么组成的。
接口组成

http://127.0.0.1:5000/door?p=open
  |        |     |     |   |    |
协议    ip/域名 端口 接口名 参数 参数值
http://127.0.0.1:5000/door?p=open
\__/  \________/ \__/ \__/\_/\__/
 |        |       |     |  \   \
协议    ip/域名  端口 接口名 参数 参数值

上图中包含6个主要部分,分别是请求协议、ip/域名、端口、接口名称、参数以及参数值,下面分别说明:

❶请求协议:

http — 普通的http请求
https — 加密的http请求,传输数据更加安全

❷请求IP/域名:

我们先简单理解为用户访问接口部署的服务器ip或域名地址,生产环境一般只对外提供域名访问,一是相对安全,二是方便运维维护

❸请求端口:

主机用来监听http请求的端口号,端口号是跟在URL的IP或域名地址后面的,用‘:’分隔开,http默认端口80,https默认端口443

❹接口名:

端口后“/”和参数前“?”中间的一串,称之为接口路径,此处简化为直接用接口名

❺接口参数:

'?'为保留字段,表示从?后面开始的为要传递的参数,参数间用“&”来区分

❻接口参数值:

参数“=”后面的即为各个参数的参数值

4. 接口实例

接下来我将用门禁实例,带你一步步做接口测试,对于门禁的接口测试,最基本的就是验证:p的值分别为“open”、“close”的时候,门是不是可以正常开门、关门。首先我们用python实现门禁接口的功能,代码如下:

#coding:utf-8
__author__ = 'Mr. null'

from flask import Flask, request, jsonify

app = Flask(__name__)

# 定义door接口,参数p值为"open"时返回开门,为"close"时返回关门
@app.route('/door',methods= ["GET"])
def door():
    p = request.args.get("p")
    if p == 'open':
        return jsonify(code=0,msg="开门")
    elif p == 'close':
        return jsonify(code=1,msg="关门")

if __name__ == '__main__':
    app.run()

运行上述代码,启动服务器,然后我们用postman工具来做接口测试

case1:正常开门请求

url栏中输入“http://127.0.0.1:5000/door?p=open”, 点击【Send】发送请求,结果如下图,我们得到了预期的返回结果{"msg": "开门"},如下图:

正常开门请求

case2:正常关门请求

如果p参数值改为“close”,则返回结果信息为{"msg":"关门"},也是我们预期的返回结果。

上面是两个接口正常进行业务逻辑处理的测试用例,那除了上面两个验证最基本功能的用例外,还有没有其他的验证点呢?我们再来看一下postman的页面,如下图:

postman测试点

里面用数字1、2、3标记3个区域,分别是请求方法、url、请求参数,对每一块的测试点进行分析:

  • 请求方法:需要考虑post等请求方法
    http的请求方法有如下9种,其中后6种只有http1.1中才有

    GET --- 获得资源
    POST --- 提交数据
    HEAD --- 类似于GET, 获取报头
    PUT --- 修改某个内容
    DELETE --- 删除某个内容
    CONNECT --- 用于代理进行传输,如使用SSL
    OPTIONS --- 查看服务器的性能
    TRACE --- 回显服务器收到的请求
    PATCH --- 对 PUT 方法的补充,局部更新 
  • url部分:需要考请求虑接口名错误,参数不存在,冗余参数等场景

  • 参数部分:需要考虑参数p是否为必填参数,参数值不为"open"、"close",参数值为null,参数值长度上下限,参数值类型以及是否包含特殊字符等场景

基于上述测试点分析,分别从中挑选1个测试点设计测试用例进行测试

case3:请求方法:post

postman工具中,将请求方法修改为[POST],发送请求,返回结果如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>

case4:参数不存在

postman工具中,删除"?"后面的参数及参数值信息,发送请求,返回结果如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or
    there is an error in the application.</p>

case5:参数值"push"

postman工具中,将参数"p"的参数值修改为"push",发送请求,返回结果如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or
    there is an error in the application.</p>

可以看到,上述3个case执行结果都有报错,说明接口存在bug,事实上,我们上述python代码确实对异常情况未做任何处理,大家也可以从开发的角度考虑下,如何修改代码才能修复上述缺陷。
报错的信息中,标签内数字为服务器状态码,常见的HTTP状态码如下(具体可参考 https://www.runoob.com/http/http-status-codes.html ):

  • 200 OK - 请求成功
  • 302 Found - 资源(网页等)被临时转移到其它URL
  • 400 Bad Request - 客户端请求的语法错误,服务器无法理解
  • 403 Forbidden - 服务器理解请求客户端的请求,但是拒绝执行此请求
  • 404 Not Found - 请求的资源(网页等)不存在
  • 500 Internal Server Error - 内部服务器错误
  • 502 Bad Gateway - 网关或者代理服务器从远程服务器接收到了一个无效的响应

上文我们介绍了接口的请求模型、接口url组成等内容,并用门禁卡的实例分析了接口测试的一些关键测试点,如果进一步深究,我们将请求url"http://127.0.0.1:5000/door?p=open"中的参数p的参数值替换为1,那这个1到底是字符型还是数值型呢?如果p的参数值包含特殊字符或中文,那url又会怎么处理呢?上述问题是很多api接口bug产生的根源,也是作为一名优秀测试人员需要理解的,下一节我们继续探讨这些问题的答案,同时,分析接口测试中涉及到的功能测试点、异常场景测试点、安全测试点、性能测试点等关键测试点,形成完整、实用的接口测试点大纲,相信对你一定会有帮助。

另外,上述门禁功能,用户手里的门禁卡是非常简陋的,就是一块卡片上面印了“open”字样,只要别人看到这个信息,就可以自己拿张卡片上面打印“open”伪造出一个门禁卡,这个伪造的门禁卡同样也可以打开门,在实际应用中怎么解决这个问题呢?《第三章-接口测试进阶篇》中,我们继续用代码实例深入分析、探讨这个问题。