1 接口
1.1 引言
为什么要学习接口测试
场景1:
小博同学在博才学成归来,效仿百度自主研发了一款搜索引擎“骑驴找马",在测试过程中发现当搜索两端有空格的关键字时,响应结果中显示的是去除了空格的关键字信息,而预期结果是不做空格去除处理的,这显然是一个BUG了,请大家思考,根据之前学习的知识,我们可以定位BUG吗?该BUG产生于前端还是后端?
场景2:
小博同学的搜索引擎还提供了注册功能,并且针对注册实现已经完成且通过了功能测试,但是项目上线一段时间
后,却发现注册了大量垃圾用户,比如:有的账号或密码超出了长度限制或是出现了空的账号或密码,错误的邮箱
格式,错误的手机格式等等…,请问为什么?
要解决上述问题,必须得学习新知识点:接口测试
接口测试主要解决就是定位前后端的问题
1.2 接口介绍
1.2.1 概念
接口:不同单元或模块之间进行通信的管道,它还是一套规范/ 标准
举例: 比如 USB 接口, 网线接口 …
内容 :是不同单元或模块直接通信的通道,此外还是一套规范/标准
- 通道
- 规范
软件方面以百度搜索为例:
- https://www.baidu.com/s ==> 建立通信通道
- https://www.baidu.com/s?wd=10010 ==> ?wd=10010符合通信的规则
1.2.2 作用
作用:数据交互
采用规范化接口的优态:
- 统一设计标准,更易于团队磨合
- 缩短研发周期
- 扩展性好
- 前后端都可以使用自己熟悉的技术,只需要保证最终产出符合规范即可
1.2.3 实现
- 用编码实现路径
- 怎样预定义接口规则?
- 预定义的接口规则会落实到文档,该文档称之为 APl(Application Program Interface)文档
- 前端和后端编码时,需要参考 API 文档
- 前人定义了一些常用的规则,如 RESTful
举例
- 编写登录接口的规范
描述:登录接口
URL: http://www.xxx.com/login PosT
提交数据:
账号 username
密码 password
响应结果:
成功 True
失败 Fa1se
2.前端和后端按照规范实现
前端:
账号: 密码:后端:
- 按照文档声明的规则,解析用户提交的数据
- 查询数据库账号密码是否合法
- 根据查询结果响应数据:合法响应 True — 非法响应 False
1.3 接口测试介绍
1.3.1 概念
接口测试:绕过前端,直接测试后端实现是否符合接口规范
1.3.2 作用
- 辅助定位bug
- 前端bug
- 后端bug
- 发现程序中的安全隐患。如QQ注册
- 前端页面填写用户名为6-10位
- 假如接口测试时,不符合该要求说明发现了一个安全隐患
- 提高测试效率
1.3.3 实现
实现流程
- 首先跨过前端,通过URL定位接口资源。如:www.baidu.com/s
- 然后提交测试数据。如:?wd=10086
- 最后判断响应结果是否符合预期,是否返回包含10086关键字的页面,符合预期
接口测试三要素
- 定位接口资源
- 提交测试数据
- 判断响应结果,预期结果来源于“需求文档”
1.3.4 分类
- B/S(web形式的接口测试)
- 服务端接口测试 --> 自实现接口
- 外部(第三方)接口测试。如:支付接口、支付宝支付、微信支付等等
- C/S(模块之间的接口测试)
2 接口测试
2.1 引言
为什么要学习Restful架构风格
需要统一进行规划
2.2 概述
概念 :Restful架构是一种接口设计架构,约束了接口实现的规范
作用 :提高了文档易读性
2.3 三要素
接口测试三要素
- 定位接口资源
- 提交测试数据
- 判断响应结果,预期结果来源于“需求文档”
在API文档中,对于接口的描述也是围绕三要素展开的
描述 :如实现用户登录的功能
流程 :
- 登录表单数据提交到服务器: http://www.xxx.com/login,请求方式 POST
- 提交数据格式: username=xxx&password=yyy
- 响应结果
- 200 {“msg”: “登录成功”}
- 200 {“msg”: “登录失败”}
2.3.1 要素一:定位接口资源
组成
-
URL
-
例如,http://www.baldu.com/s
-
它是统一资源定位符
-
内容
-
协议:常见的协议有 http/ https/ ftp/ ftps
-
IP:服务器的IP地址
-
端口
- http默认端口一般是80
- https默认端口一般是443
-
路径:一个资源路径对应一个接口实现
-
-
-
请求方式
- GET:查
- POST:增
- PUT:改
- DELETE:删
-
get 和 post 区别
- 提交方式不同
- get提交的数据可以显示在地址栏
- post是隐式提交数据,更加安全
- 可提交的数据量不同
- get提交的数据量有限制的
- post提交的数据量无限制
- 执行效率不同:get执行效率比post高
- 提交方式不同
2.3.2 要素二:提交数据
-
两种常见的提交方式
- 键值对
- JSON(类似于python中字典)格式
-
举例
-
键值对:
username=laoliao&password=111111&aihao=chuiniu&aihao=aaa&aihao=bbb
-
JSON格式:
{ "username": "laoliao", "password": "111111", "aihao": ["chuiniu", "aaa", "bbb"] }
一般情况下,使用get方式进行提交时,使用的是键值对格式
使用post方式进行提交时,使用的是json格式
-
2.3.2 要素三:判断响应结果
-
状态码
-
1xx:请求正常,但无响应,只在实验状态下使用
-
2xx:请求正常,响应正常,如:200,201,204
-
3xX:以其他方式获取响应,如:302重定向304取本地缓存
-
4xx:浏览器端异常,如:404资源路径有误
-
5xX:服务器端异常,如:500服务器运行异常
-
-
响应体
- 常见两种类型:
- 响应html类型文档:比如访问百度搜索接口
- 响应JSON数据
- 常见两种类型:
请求方式 | 要素一 | 要素二 | 要素三 |
---|---|---|---|
查 | URL + GET | 键值对提交 | 状态码:200 响应体:单条或多条数据 |
增 | URL + POST | 键值对/JSON提交 | 状态码:200或(201) 响应体:新增后的数据 |
改 | URL + PUT | 键值对/JSON提交 | 状态码:200 或(201) 响应体:修改后的数据 |
删 | URL + DELETE | 键值对提交 | 状态码:204 响应体:无 |
Restful只是一种规则,并不是标准,换言之,不是硬性约束
3 环境搭建
3.1 环境分析
-
项目
项目由java编写, 需要编译后才能运行
- JDK
- IDE
- Tomcat
- MySQL
-
测试
依赖测试工具, 如
- 浏览器
- postman(开发人员用得多)
- Jmeter(测试人员用得多)(核心工具)
3.2 手动部署
3.2.1 安装
运行jdk-8u211-windows-x64.exe文件(例如我的安装目录:D:\Java\jdk1.8.0_211)
推荐使用 1.8的 64位的版本
安装目录尽量不要有中文或者空格等特殊字符
配置环境变量
1.进入我的电脑 -> 属性 -> 高级系统设置 -> 环境变量
2.在系统变量下点击新建 -> 变量名: JAVA_HOME ->
变量值: D:\Java\jdk1.8.0_211 -> 点击确定按钮
3.在系统变量下点击新建 -> 变量名: CLASSPATH ->
变量值: .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar -> 点击确定按钮
4.在系统变量下找到系统的Path变量,进入在最后添加:;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
-> 点击确定按钮
新增系统变量 JAVA_HOME
新增系统变量 CLASSPATH
修改Path变量的值, 增加 ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin 即可
注意: Path变量值非常重要, 编辑前请先备份
验证
命令行输入 java -version 输出java的版本号即可
3.2.2 Tomcat
- 下载
https://tomcat.apache.org/ - 解压
把下载得到的 xxx.zip 直接解压到某个目录即可 - 配置
D:\apache-tomcat-8.5.47\conf 找到 server.xml 可以看到 Tomcat 默认http端口是 8080 - 运行
windows 下使用bin目录下的 startup.bat
linux 下使用bin目录下的 startup.sh
3.2.3 MySQL
下载安装
使用 phpStudy 自带的 MySQL 服务即可
启动步骤
- 启动 phpStudy
- 右键到 “启动” 按钮
- 左键单击 “启动MySQL” 即可
说明
- java项目会去连接本机的 MySQL
- 要求有一个名为 test 的数据库
- 数据库名为 test
- 字符集为 utf8
- 排序规则为 utf8_general_ci
- 执行 sql 文件, 生成名为 t_area 的数据表 并且新增一条数据
sql文件代码
/*
Navicat Premium Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50553
Source Host : localhost:3306
Source Schema : test
Target Server Type : MySQL
Target Server Version : 50553
File Encoding : 65001
Date: 17/02/2020 17:41:13
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_area
-- ----------------------------
DROP TABLE IF EXISTS `t_area`;
CREATE TABLE `t_area` (
`area_id` int(12) NOT NULL AUTO_INCREMENT,
`area_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`priority` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0',
`create_time` datetime NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`area_id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_area
-- ----------------------------
INSERT INTO `t_area` VALUES (1, '东西南北中', '0', '2020-01-01 19:00:00', '2020-01-01 19:00:00');
SET FOREIGN_KEY_CHECKS = 1;
3.2.4 MySQL[补充]
为什么一定要连接名为test的数据库
是代码中写死的配置
配置信息补充
数据库要求本地 localhost
数据库名要求为 test
登录数据库的用户名要求为 root
登录数据库的用户密码要求为 123456
4 项目运行
编译打包
得到可执行文件 api-1.0.jar
运行
- 在jar文件所在目录打开命令行
- 输入 java -jar api-1.0.jar 并回车
验证
- 看到 Started xxx in xxx seconds 时, 表示成功运行
- 访问程序的某个接口, 返回值正确, 则说明运行成功
5 测试工具
工具分类
-
浏览器
- 不算插件, 浏览器本身只能帮助测试 get 方式的请求
- 缺少用例组织能力
-
主流工具
-
postman: 功能强大 (建议在学习完 jmeter 后, 自学, 面试可能用到)
-
jmeter: 核心讲解, 开源/ 支持多协议/ 免安装/ 性能测试
jmeter 应用领域:
- 接口测试
- 性能测试
- 压力测试
- 自动化测试
- 数据库测试
-
5.1 jmeter
下载
地址: http://jmeter.apache.org/download_jmeter.cgi
解压
(注意解压目录问题)
启动
- 方式1: 找到bin目录下对应系统的可执行文件, 如 windows下用 jmeter.bat
- 方式2: 命令行启动 (需要提前配置环境变量)
配置
- 配置中文菜单显示
- 进入 jmeter 解压目录下的 bin 目录
- 找到并打开 jmeter.properties
- 查找 #language=en 改为 language=zh_CN
- 考虑中文乱码
- 进入 jmeter 解压目录下的 bin 目录
- 找到并打开 jmeter.properties
- 查找 sampleresult.default.encoding 改为 sampleresult.default.encoding=UTF-8
5.2 Jmeter基本使用流程
启动项目案例
- 启动 mysql 服务
- 启动 api-1.0.jar
- 验证服务启动是否成功 http://localhost:8081/sa/listarea 请求到数据即可
使用步骤
-
启动 jmeter 并搭建基本框架
- 线程组: 测试计划右键 -> 线程(用户) -> 线程组
- http请求: 线程组右键添加 -> 取样器 -> HTTP请求
- 察看结果数: 线程组右键添加 -> 监听器 -> 察看结果数
-
设置接口测试三要素
设置要素一和要素二
默认值: 协议 http 端口号 80 编码 utf-8
-
保存计划, 运行并查看结果
5.2 Jmete的组件与元件
组件:Jmeter中的一些功能点实现, 如, 线程组 http请求 察看结果数
元件: 对组件按照性质归类分组, 作用: 方便管理组件
5.3 环境变量
概念
环境变量是操作系统中一个具有特定名字的对象, 它包含了一个或者多个应用程序将使用到的信息
例如, windows 中的 Path 变量
当系统要运行一个程序时, 假如在当前目录找不到, 就会去 Path 中包含的目录去查找
作用
设置参数, 提供方便
例如:
把 jmeter 的bin目录配置到 Path变量中, 使我们可以在任意目录输入 jmeter 来启动服务
5.4 环境变量优化
思考
不建议频繁修改Path, 操作Path有风险
如果路径变动, 需要更新环境变量, 怎么办?
优化策略
- 创建一个新的系统变量, 名为 XXX_HOME, 变量值为项目的安装或解压的根目录
- 在 Path 中配置路径时, 引用刚才创建的变量, 如: %XXX_HOME%\bin
- 以后需要更新路径时, 不需要操作 Path, 只修改第一步创建的变量即可, 更安全
5.5 Jmeter组件de 线程组
概念
-
进程: 正常运行的程序
程序启动, 进程创建, 程序关闭, 进程释放
-
线程: 程序中的执行路径
如, 迅雷中每一部电影的下载, 游戏中的每个角色
-
线程组: 对线程分类归组
层级关系
进程 > 线程组 > 线程 : 一个进程可以包含多个线程组, 一个线程组可以包含多个线程
线程执行顺序
-
顺序执行: 多个线程按照顺序执行, 线程的启动和结束顺序是一致的
如, 电影需要先下载再播放
-
并发执行: 多个线程同时执行, 线程的启动和结束顺序不一定一致
如, 多部电影同时下载
线程组作用
方便管理线程
5.6 Jmeter组件de 线程组层级关系和执行顺序
默认执行顺序
jmeter 的默认执行顺序是并发执行
“独立运行每个线程组”
测试计划中, 勾选"独立运行每个线程组"后, 执行顺序变为顺序执行
5.7Jmeter组件的线程组常见属性设置和特殊线程组
setUp线程组: 最先执行的线程组, 一般用于初始化操作
tearDown线程组: 最后执行的线程组, 一般用于资源销毁
5.8 Jmeter组件-线程组查看结果数的作用域
查看结果数显示线程组内取样器的执行结果, 位置不同, 对应生效的取样器也不同
- 添加在测试计划: 对所有线程组的所有取样器生效
- 添加在线程组下: 对当前组内取样器生效
- 添加在取样器下: 只对当前取样器生效
5.9 Jmeter参数化
概念
动态(程序代替人工)生成/设置/导入数据
作用
- 高效
- 安全
- 功能: 更强大
5.10 实现
四种实现方式
- 用户定义的变量
- 用户参数
- 函数(重点)
- csv数据文件设置(重点)
说明: 四者互补
5.11 用户定义的变量
步骤
-
编写脚本
-
封装: 测试计划/线程组右键添加 -> 配置元件 -> 用户定义的变量 组件, 添加对应的变量
-
调用: 通用方式-在 http请求中, 对应的字段, 使用 ${变量名} 进行调用
5.12 用户参数
步骤
- 编写脚本
- 存储测试数据(不需要依赖外部文件, 用户数少的时候适合使用)
- 调用 ${变量名}, 注意: 设置线程组的线程数, 一般有几个用户就设置几次
5.13 函数
步骤
- 编写脚本
- 打开函数助手(鼠标悬停在工具栏, 会有提示)
- 选择所需函数, 生成能够被调用的格式
- 调用: 哪里需要粘哪里(注意需要设置线程组的循环次数)
常用函数介绍
- __counter() 计数器
- __Random() 生成随机数(少量随机数的时候)
- __time() 时间函数
- __UUID() 生成随机ID(大量随机数的时候)
5.14 csv数据文件设置
补充内容
- csv文件其实就是格式化的txt文件
- csv文件用逗号分隔值
- txt换csv: 把文件后缀的txt改为csv即可
在jmeter中, 直接读取txt文件也是可以的
步骤
- 准备脚本和csv数据文件
- 调用
- 常规调用, 设置循环次数, 有几条数据就设置线程组的循环次数为几
- 非常规调用
- 在线程组设置中勾选"永远"
- 修改csv数据文件设置组件的配置
- 把遇到文件结束符再次循环? 设置为 False
- 把遇到文件结束符停止线程? 设置为 True
5.15Jmeter直连数据库
概念
直连: jmeter -> 直接访问数据库
非直连: jmeter -> 访问 java/python 提供的接口 -> 访问数据库
作用
获取数据(对比结果(断言))
步骤
-
准备脚本 并导入第三方包 (因 jmeter 不具备直接连接数据库的功能)
-
配置数据库连接信息
- 添加配置元件 -> JDBC Connection Configuration 配置数据库的连接信息
- 连接名称 mysql
- jdbc:mysql://localhost:3306/test
- driver: 选择 com.mysql.jdbc.Driver
- 登录名: root
- 登录密码: 123456
- 添加配置元件 -> JDBC Connection Configuration 配置数据库的连接信息
-
向数据库发送sql语句并接收响应结果
- 线程组右键添加 -> 取样器 -> JDBC Request
- 选择 连接名称
- 输入sql语句
- 输入接收的变量名
- 线程组右键添加 -> 取样器 -> JDBC Request
-
处理接收到的响应结果 (如, 在百度上搜索)
5.16 Jmeter断言
概念
程序驱动代替人工驱动, 判断响应结果是否符合预期
分类
响应断言
大小断言
作用
-
高效
-
安全
步骤
- 准备脚本
- 添加断言: 具体某个请求上右键添加 -> 断言 -> 响应断言 (大多数情况适用相应断言即可)
- 运行并查看结果
- 通过 没有提示
- 不通过 有错误提示
5.17 Jmeter逻辑控制器
应用场景
比如要下订单, 需要先登录:
- 登录成功, 则可以继续下订单
- 登录失败, 则不能下订单
if 登录接口, 执行结果为 成功:
执行下订单请求的接口, 预期下订单成功
else:
执行再次登录的接口, 预期结果为登录成功
此时, 就需要通过逻辑控制器实现
概念
控制接口(取样器)执行顺序的组件
- 顺序执行
- 分支执行 == if 语句 == 如果(if)控制器
- 循环执行 == for/ while 语句 == ForEach控制器 / 循环控制器
作用
控制执行逻辑
如果(if)控制器
步骤
- 搭框架: 测试计划/ 线程组/ 查看结果数/ 添加一个用户定义的变量
- 核心: 以分支方式控制取样器的执行(逻辑控制器和取样器是父子级关系)
- 运行并查看结果
ForEach控制器
步骤
- 搭框架: 测试计划/ 线程组/ 查看结果数/ 添加一个用户定义的变量
- 核心: 以循环的方式控制取样器的执行(逻辑控制器和取样器是父子级关系)
- 运行并查看结果
循环控制器
步骤
- 搭框架: 测试计划/ 线程组/ 查看结果数
- 核心: 以循环的方式控制取样器的执行(逻辑控制器和取样器是父子级关系)
- 运行并查看结果
线程组和循环控制器的循环控制的区别
二者作用域不同, 相对来说循环控制器更灵活一点
6 Jmeter关联
应用场景
测试考试交卷的接口, 需要学生先登录, 再进行交卷操作
概念
上一个请求的响应结果作为下一个请求的参数
作用
在接口测试中所涉及的不同接口间传递数据
6.1 实现
需求
访问京东(请求A), 提取页面源码中的 title 标签的值, 传递给百度搜索(请求B)
6.2 XPath提取器
步骤
- 搭框架
- 从响应结果中提取
- 右键 http请求 -> 添加 -> 后置处理器 -> XPath提取器
- 调用提取到的数据, ${变量名}
6.3 正则表达式提取器
步骤
- 搭框架
- 从响应结果中提取
- 右键 http请求 -> 添加 -> 后置处理器 -> 正则表达式提取器
- 调用提取到的数据, ${变量名}
扩展
正则表达式(通过特殊符号来指定一定的匹配规则)
(.*?) 一般来说,使用这个规则可以解决大部分问题
() 表示截取区间
. 表示任意字符
* 表示出现任意次
.* 表示任意字符串
? 表示截取到第一个结束标记
6.4 正则表达式提取器与XPath提取器二者比较
相同点
- 二者实现流程一致
- 都可以从响应结果提取数据
不同点
-
XPath提取器 只能从标签文档(如, html 或 xml)提取数据, 一般文本数据无法使用
-
正则表达式提取器 既适用于标签文档又适用于一般文本文档, 作用范围更广
推荐大家重点掌握正则表达式提取器
6.5 跨线程组关联
需求
在前一个需求的基础上, 把请求A和B放到不同的线程组中, 并且设置了线程的执行顺序, 先A后B, 但是关联失败, 通过跨线组关联让它关联成功
原因: 变量作用域不对
解决: 将局部变量转换成全局变量
步骤
- 搭框架
- 把局部变量转换成全局变量
- 建立局部变量和全局变量的对应关系 (通过函数 __setProperty)
- 导出为全局变量 (通过 Bean Shell 取样器)
- 调用全局变量 (通过 __Property)
6.6 Jmeter定时器
常用定时器有什么
-
同步定时器
-
常数吞吐量定时器
常用定时器作用是什么
用于性能测试
6.7 Jmeter分布式性能测试-1-概述
应用场景
单台测试机不能产生足够的并发数, 需要多台测试机测试服务器性能
概念
分布式: 多台测试机协作, 以集群方式共同完成测试任务
作用
产生海量并发
角色划分
控制机: 负责任务分配
执行机: 负责任务实现
工作流程
- 控制机制定测试任务, 并下发到执行机
- 执行机执行任务并将结果返回给控制机
- 控制机做结果汇总
7 Jmeter总结
7.1 作用域
概念
作用范围, 在 jmeter 中专指当前组件对哪些范围的取样器生效
7.2 执行顺序
jmeter中组件的执行顺序与添加顺序不一定有关系, jmeter的组件有默认的执行顺序
我们可以通过元件的执行顺序去判断组件的执行顺序
7.3 图形化测试报告
在jmeter中可以以图形化(饼状图, 柱状图…)的方式显示脚本运行结果, 它比聚合报告或查看结果数的显示更直观, 用户体验更友好
8 接口测试流程
-
制定测试计划: 分配任务
- 任务名称: 按模块去划分
- 任务描述: 说明具体任务内容
- 责任人
- 工期: 以天为单位
- 开始日期
- 结束日期
- 进度: 进行中/未开始
- 备注
-
从 API 文档中提取接口清单
接口清单是对 API 文档的精简
- API文档为了保证易读性, 说明信息较多, 导致测试过程中, API 文档内容稍显冗余
- 需要从 API 文档提取测试必须的数据, 摒弃冗余数据 (提取的结果: 接口清单)
-
设计测试用例并参数化覆盖测试用例
-
编写脚本实现, 导入设计的测试数据
-
生成测试报告
- 接口功能名称
- 接口用例描述
- 预期结果
- 实际结果
- 是否Bug
- 备注
9 接口测试原则
9.1 功能测试原则
原则
- 设计各种正向 + 逆向的测试用例
- 接口覆盖率达到100%
9.2 自动化测试原则
原则
- 接口覆盖率没必要100%, 只需要测试重要的和被重复调用的接口
- 只需要提交正向的测试用例
- 自动化脚本需要保证可以重复执行
- 一个线程组建议对应一个取样器
9.3 性能测试原则
应用场景
- 高并发
- 高频率
- 区间多用户
原则
1 线程组: 增删改查每个功能, 都需要单独的线程组, 而且避免在同一个线程组内有多个取样器
2 参数化: 参数化尽量避免从外部(csv文件)读取数据, 而是用函数生成测试数据
3 查看结果树: 必须清除单个请求内的查看结果树组件, 建议一个测试计划就一个查看结果树
4 报告: 性能测试报告可根据实际需求选择, 建议使用 聚合报告
5 分布式
扩展
二八原则: 指80%业务量在20%的时间内完成