使用 Jmeter 做 Web 接口测试-详解

时间:2024-01-30 07:31:15

接口测试概述

定义

WIKI定义:接口测试作为集成测 试的一部分,通过直接控制API来判断系统的功能性,可靠性,性能与安全性。API测试是没有界面的,执行在通讯 层。API 测试在自动化测试中有着重要的地位,因为API一般是应用逻辑的主要接口,而GUI测试在敏捷开发和DevOps的快速迭代和频繁变更中很难维护。

什么是接口测试?

  接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。
  接口测试适用于为其他系统提供服务的底层框架系统和中心服务系统,主要测试这些系统对外部提供的接口,验证其正确性和稳定性。接口测试同样适用于一个上层系统中的服务层接口,越往上层,其测试的难度越大。
  接口测试实施在多系统多平台的构架下,有着极为高效的成本收益比,接口测试天生为高复杂性的平台带来高效的缺陷监测和质量监督能力。平台越复杂,系统越庞大,接口测试的效果越明显。
  基于接口测试的重要性,以及它比较容易自动化的特性,通过持续集成的接口监控能够及时的发现项目中存在的问题,这对持续运营的项目来说,非常重要。

接口测试的流程

  1、 项目启动后,测试人员要尽早找到开发人员拿到接口测试文档
  2、 获取接口测试文档后,就可以进行接口用例的编写和调试
  3、 接口用例编写调试完成后,部署到持续集成的测试环境中,
  4、 设定脚本运行频率,告警方式等基本参数,进行接口的日常监控
  5、 每日进行接口脚本的维护更新,接口异常的处理

分类

接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。接口测试大体分为两类:模块接口测试和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数据库为例


其它数据库连接请参考下图:

  • 添加JDBC request


因为我们在接口测试中,更多的时候是获取数据,所以基本都用“SELECT"。如果想INSERT数据,需要选择“Callable Statement"在"Query Type"

在使用过程中注意以下几点:

  • SQL语句不要加分号

  • 如果查询条件是变量,在语句中用“?”号代替,具体的值在下面的“Parameters Value"定义,如果有多个参数,中间要用分号隔开。当然也可以用${变量名}(在用户定义变量组件中已经定义)

  • 对于“variable names" 数据表中有多少列就可以设置多少变量,对于不需要设置变量的列用逗号占位就可以了。

  • 更具体的使用细节请参考(http://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次,那么这里显示100
Average:平均响应时间——默认情况下是单个 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