接⼝测试概述
WIKI 定义:接⼝测试作为集成测试的⼀部分,通过直接控制 API 来判断系统的功能性,可靠性,性能与安全性。API 测试是没有界⾯的,执⾏在通讯层。API 测试在⾃动化测试中有着重要的地位,因为API ⼀般是应⽤逻辑的主要接⼝,⽽ GUI 测试在敏捷开发和 DevOps 的快速迭代和频繁变更中很难维护。
分类
接⼝测试是测试系统组件间接⼝的⼀种测试。接⼝测试主要⽤于检测外部系统与系统之间以及内部各个⼦系统之间的交互点。测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。接⼝测试⼤体分为两类:模块接⼝测试和 web 接⼝测试。
模块接⼝测试
模块接⼝测试是单元测试的基础。它主要测试模块的调⽤与返回。经常需要编写⼀些桩模块与驱动模块。
主要测试要点如下:
- 检查接⼝返回的数据是否与预期结果⼀致。
- 检查接⼝的容错性,假如传递数据的类型错误时是否可以处理。
- 接⼝参数的边界值。例如,传递的参数⾜够⼤或为负数时,接⼝是否可以正常处理。
- 接⼝的性能,接⼝处理数据的时间也是测试的⼀个⽅法。牵扯到内部就是算法与代码的优化。
- 接⼝的安全性
WEB 接⼝测试
web 接⼝测试⼜可分为两类:服务器接⼝测试和外部接⼝测试。
服务器接⼝测试:是测试浏览器与服务器的接⼝。⽤户输⼊的数据是输⼊到的前端⻚⾯上,怎样把这些数据传递的后台的呢?通过 http 协议的 get 与 post 请求来实现前后端的数据传递。这也可认为是接⼝测试。
外部接⼝测试:这个很典型的例⼦就是第三⽅⽀付,⽐如在我们应⽤中在充流量时,交话费时,都会调⽤第三⽅⽀付接⼝。
主要测试要点如下:
- 请求是否正确,默认请求成功是 200,如果请求错误也能返回 404、500 等。
- 检查返回数据的正确性与格式;json 是⼀种⾮常常⻅的格式。
- 接⼝的安全性,⼀般 web 都不会暴露在⽹上任意被调⽤,需要做⼀些限制,⽐如鉴权或认证。
- 接⼝的性能,这直接影响⽤户的使⽤体验。
接⼝测试⼯具
- SOAPUI
- JMeter
- Grinder
- Suds Python
在⼯作中主要应⽤ SOAPUI 与 JMeter。SOAPUI 对接⼝安全测试有⽐较好的⽀持。本⽂还是主要介绍 JMeter 的使⽤,关注的是功能测试,对于它的强项性能测试,在以后的⽂章中描述。
测试⽤例设计与原则
因为在实际⼯作中测试的接⼝都是基于 HTTP 协议的,所以下⾯的测试⽤例及原则也是针对此类接⼝。
测试⽤例
正⾯测试⽤例:
- 覆盖所有的必选参数
- 组合可选参数
- 参数边界值
- 如果参数的取值范围是枚举变量,需要覆盖所有枚举值
- 还应考虑实际业务应⽤场景,去设计输⼊参数的组合。(这些⽤例可⽤来测试功能,作为 SMOKE ⽤例。也可将来⽤于压⼒测试模拟实际业务场景,但要注意保证⽤例的独⽴性,因为压⼒测试是多线程的。⽐如我们测试 ACCOUNT 创建接⼝,NAME 是不能重的,在写测试⽤例时,给 NAME 赋值时可以加⼀个时间戳, 这样⽤例在多线程并发测试时也不会有问题)
负⾯测试⽤例:
- 空数据
- 包含特殊的字符
- 越界的数据
- 错误的数据
验证点:
- status code(正常情况下,所有请求都应该返回 200)
- 响应信息数据结构(⽬前⼤多数情况下,返回信息都是 JSON, 我们应该验证相应的结构当数据信息发⽣改变时)
- 验证结点的类型
- 验证结点的值(主要是针对固定的值或者值遵循某些规则,我们能知道预期的结果的)
- 对于列表,应该根据请求参数,也应该验证列表的⻓度是否与期望值⼀致
- 负⾯测试⽤例,应验证 ERROR INFO 是否与实际相匹配
测试原则
- 测试应该是独⽴的、可读的、抗变的、可维护的,其实这也是所有⾃动测试应该遵循的原则
- 每个测试⽤例都是独⽴的
- 测试⽤例都是可重复运⾏的 (这主要是说⼀些测试数据不能写死,不同的环境数据可能不同。在实际⼯作中,解决⽅案有⼆:⾃已创建所需要的数据,⽐如你要测试接⼝需要输⼊参数 ACCOUNTID,你可以先调⽤创建 ACCOUNT API, 然后从响应值拿到 ACCOUNTID, 当你测试完你要测的接⼝后,再把新建的 ACCOUNT 删除,也就是说⼀个测试⽤例分了三步。另外⼀种⽅法就是读取数据库,从数据库获取数据,这种⽅法在测试开发与测试环境还 OK,但如果测线上环境就⽐较困难了,因为我们不能随意更新上⾯的数据,也不能放过多的测试数据在上⾯。因此我个⼈⽐较推崇第⼀种⽅法,虽然增加开发⽤例的⼯作量,但⼀劳永逸)
- 测试能被运⾏在不同的环境⾥(平常测试环境⾄少会分DEV/TEST/STAGING/ONLINE,我们在测试过程中,应该把域名,token/apikey 等应放在⼀个变量⾥,当切换环境时,我们只需改变变量的值即可测试数据与业务相分离(测试数据包括参数接⼝数据/ 测试执⾏所需要的系统数据)
- 尽量统⼀共⽤的测试环境变量
- 测试完成后,要删除不必要的测试数据。
JMeter 使⽤
在实际⼯作中,我主要应⽤ JMeter 对接⼝做功能测试,所以下⾯主要介绍⼀下 JMeter 的使⽤
基本介绍
下⾯是我的⼀个测试脚本,通常⼀个⽂件会包含下⾯这些组件。我通过简单控制器与DEBUG Sampler 来组织管理不同的接⼝,验证点主要通过写⼀些 Beanshell 脚本来实现。对于⼀些复杂的操作,如果⽹上能找到到现成的资源,⽐如 JAR,CLASS ⽂件会直接在 Beanshell PreProcessor/PostProcessor 引⽤。另外在 Jmeter ⾥写 Beanshell 不容易 DEBUG,所以还是建议复杂的功能直接在 Eclipse ⾥编写,然后⽣成 JAR 包. 关于 Beanshell 使⽤会在后⾯介绍
使⽤ Beanshell 在 JMeter
BeanShell 是⼀种完全符合 Java 语法规范的脚本语⾔,并且有⾃⼰的⼀些语法和⽅法官⽹:http://www.beanshell.org/
我的脚本⼏乎所有验证都是通过 Beanshell 脚本,只有少部分应⽤了 Response Assert。
Beanshell 常⽤内置变量
http://jmeter.apache.org/api/org/apache/jmeter/threads/
下⾯是⼀些实际的例⼦
- 操作变量:(vars)
- 获取前⾯的 sample 返回的信息(prev)
- 写⼊信息到 jmeter.log ⽂件
log.info("log information")
- 获取属性(props)
它是类似的与 vars, 相应的属性在在⽂件 jmeter.properties 中定义
- 引⽤外部⽂件(jar/class/java)
另外如果引⽤外部 JAR 包,也可在 TEST PLAN 中配置,在 JMeter 中点击 Test Plan
结点,就会看到下⾯的界⾯,可以直接添加 JAR 包所在路径
其它
CSV 配置组件使⽤
CSV_Data_Set_Config 当发送多组同样的请求,只是所带参数不同,这时可以加这个配置组件
然后在 SAMPLER 中可以应⽤上⾯这些变量配合循环控制器
连接数据库
在测试过程中,我们需要⼀些测试数据来⾃于数据库,这时我们需要在 Jmeter 连接数据库
下⾯以连接 MySQL 数据库为例
- 下载 MySQL JDBC driver 从(https://dev.mysql.com/downloads/connector/j/5.1.html)
- 拷⻉这个⽂件到 JMeter 安装路径下的 “lib"⽂件夹
- 建⽴ “JDBC Connection Configuation"
其它数据库连接请参考下图:
- 添加 JDBC request
因为我们在接⼝测试中,更多的时候是获取数据,所以基本都⽤ “SELECT"。如果想 INSERT 数据,需要选择 “Callable Statement"在"Query Type"
在使⽤过程中注意以下⼏点:
- SQL 语句不要加分号
- 如果查询条件是变量,在语句中⽤ “?” 号代替,具体的值在下⾯的 “Parameters Value"定义,如果有多个参数,中间要⽤分号隔开。当然也可以⽤ ${变量名}(在⽤户定义变量组件中已经定义)
- 对于 “variable names" 数据表中有多少列就可以设置多少变量,对于不需要设置变量的列⽤逗号占位就可以了。
- 更具体的使⽤细节请参考(https://jmeter.apache.org/usermanual/component_reference.html#JDBC_Request)
- 获取查询结果数据在 Beanshell ⾥
添加监听器
- View result tree
- Aggregate report
Aggregate Report 是 Jmeter 常⽤的⼀个 Listener, 中译为 “聚合报告”,每⼀列具体表示如下。
Label:每个 JMeter 的 element(例如 HTTP Request)都有⼀个 Name 属性,这⾥显示的就是 Name 属性的值
#Samples:表示你这次测试中⼀共发出了多少个请求,如果模拟 10 个⽤户,每个⽤户迭代10 次,那么这⾥显示 100Average:平均响应时间——默认情况下是单个 Request 的平均响应时间,当使⽤了 Transaction Controller 时,也可以以 Transaction 为单位显示平均响应时间
Median:中位数,也就是 50% ⽤户的响应时间
90% Line:90% ⽤户的响应时间
Min:最⼩响应时间
Max:最⼤响应时间
Error%:本次测试中出现错误的请求的数量/请求的总数
Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),当使⽤了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second数 KB/Sec:每秒从服务器端接收到的数据量,相当于 LoadRunner 中的 Throughput/Sec
Jmeter 与 Jekins 集成
说这个之前简单说⼀下如何在命令⾏执⾏ JMeter
- ⾸先配置 JMETER_HOME 环境变量,值即为你 Jmeter 解压路径
- 在命令⾏运⾏ jmeter -v , 正确返回当前版本,证明环境 OK
- 运⾏ jmeter -n -t script.jmx -l log.jtl