postman基础用法
案例1、提交字符串数据
案例2、 提交form表单数据
案例3、提交json数据
Postman高级用法
一、用例管理
作用:规范法管理接口上的大量测试用例
实现步骤:
1. 创建集合—项目(如IHRM、tpshop)
2. 创建文件夹—模块(如:登录、员工管理)
3. 创建请求—测试用例(如:登录成功)
二、Postman断言
1、断言前置基础
断言:通过代码自动判断实际运行的结果是否与测试用例中的预期结果一致
断言结果:
结果一致:测试通过pass
结果不一致:测试不通过fail
Postman的断言
使用JavaScript语言编写的,写在Postman的【Tests】 标签中
【Tests】中的脚本在发送请求之后执行,它会把断言的结果(PASS/FAIL)最终在【TestResults】 标签页中
Postman的常用断言
断言响应状态码是否为200(Status code is 200)
断言响应体JSON数据校验(Response body:JSON value check)
断言响应体是否包含指定字符串(Response body: Contains string)
断言响应体是否等于指定字符串(Response body:Is equal to a string)
断言响应头是否包含指定的头信息(Response headers: Content-Type headercheck)
2、Postman断言
2.1 断言响应状态码(重点)
样例代码:
pm.test(“Status code is 200”, function () {
pm.response.to.have.status(200);
});
说明:
pm.test是postman内置对象pm对外提供的一种名称为test的方法,他的功能是使用pm.test来编写测试脚 本时,即使方法内部处理内容出现错误也不会影响后续自动化脚本的运行。
案例:
1.请求IHRM项目的登录接口,请求数据({“mobile”:“13800000002”,“password”:“123456”})
2.登录接口地址URL:http://ihrm-test.itheima.net/api/sys/login
3.请设置断言自动判定服务器响应状态码为200
断言json(重点)
示例代码:
pm.test(“Your test name”, function () {
var jsonData = pm.response.json();
pm.expect(jsonData.value).to.eql(100);
});
说明:var是用来声明javascript的变量,上面的代码等价于下面的代码。
pm.test(“Your test name”, function () {
pm.expect(pm.response.json().value).to.eql(100);
});
案例:
1.请求IHRM项目的登录接口,请求数据({“mobile”:“13800000002”,“password”:“123456”})
2.登录接口地址URL:http://ihrm-test.itheima.net/api/sys/login
3.请设置断言自动判定服务器响应体数据中success=true,code=10000,message=操作成功!
排错说明:
(1)检查断言代码片段是否选错了
(2)检查断言代码是否设置错了 预期结果或者是判断实际结果的字段选择错误
(3)先点击发送,基于响应中的body数据做初步预判
(4)检查请求相关参数(请求方式、请求头、请求体)
2.3 断言包含指定的字符串内容(知道)
样例代码:
pm.test(“Body matches string”, function () { pm.expect(pm.response.text()).to.include(“string_you_want_to_search”);
});
案例:
1.请求IHRM项目的登录接口,请求数据({“mobile”:“13800000002”,“password”:“123456”})
2.登录接口地址URL:http://ihrm-test.itheima.net/api/sys/login
3.请设置断言自动判定服务器响应体数据中包含【操作成功】
思考:怎么完整的匹配一个JSON返回数据呢?
// 服务器响应体数据中等于【操作成功】精确查找
pm.test(“服务器响应体数据中等于【操作成功】精确查找”, function () {
pm.response.to.have.body( ‘{“success”:true,“code”:10000,“message”:“操作成 功!”,“data”:“9ad2a988-e618-47ec-9498-1efe9535c88e”}’);
});
2.5 断言响应头标签(了解)
示例代码:
pm.test(“Content-Type is present”, function () {
pm.response.to.have.header(“Content-Type”);
});
案例:
1.请求IHRM项目的登录接口,请求数据({“mobile”:“13800000002”,“password”:“123456”})
2.登录接口地址URL:http://ihrm-test.itheima.net/api/sys/login
3.请设置断言自动判定服务器响应头中包含Content-Type和Content-Length
3、断言综合练习
1.请求IHRM项目的登录接口,请求数据({“mobile”:“13800000002”,“password”:""})
2.登录接口地址URL:http://ihrm-test.itheima.net/api/sys/login
3.请设置断言自动判定服务器:
(a)响应状态码为200
(b)响应体数据中success=false,code=20001,message=用户名或密码错误,data=null
©响应体数据中包含【用户名或密码错误】
(d)响应体数据等于【false】
(e)响应头中包含Content-Type
// 3.请设置断言自动判定服务器:
// (a)响应状态码为200 pm.test(“Status code is 200”, function () { pm.response.to.have.status(200); });
// (b)响应体数据中success=false,code=20001,message=用户名或密码错误,data=null pm.test(“Your test name”, function () { var jsonData = pm.response.json(); pm.expect(jsonData.success).to.eql(false); }); pm.test(“Your test name”, function () { var jsonData = pm.response.json(); pm.expect(jsonData.code).to.eql(20001); }); pm.test(“Your test name”, function () { var jsonData = pm.response.json(); pm.expect(jsonData.message).to.eql(“用户名或密码错误”); });
// ©响应体数据中包含【用户名或密码错误】 pm.test(“Body matches string”, function () { pm.expect(pm.response.text()).to.include(“用户名或密码错误”); });
// (d)响应体数据等于【false】 pm.test(“Body is correct”, function () { pm.response.to.have.body(false); });
// (e)响应头中包含Content-Type pm.test(“Content-Type is present”, function () { pm.response.to.have.header(“Content-Type”); });
三、环境变量与全局变量
1、概念
全局变量:作用范围是针对postman下面所有测试集均生效
环境变量:
只对选择了对应环境的测试集生效(如:选择了测试环境的测试集IHRM0720)
开发环境、测试环境、生产/线上环境
一套环境中变量不能重复、但是可以定义多个不重复的变量
2、设置变量
全局变量
手动设置
代码设置
//设置全局变量
pm.globals.set(“g_name”, “jack”);
//设置环境变量
pm.environment.set(“e_name”, “rose”);
3、获取变量
全局变量与环境变量
在请求参数中获取:{{变量名}}
// 设置环境变量 pm.environment.set(“e_name”, “rose”);
URL
请求头
请求体
加通过代码来获取
pm.environment.get(“variable_key”);
pm.globals.get(“variable_key”);
// 获取环境变量的值 mobile2和password2
var mobile = pm.environment.get(“mobile2”);
var password = pm.environment.get(“password2”);
console.log(“测试环境中的mobile是:” + mobile)
console.log(“测试环境中的password是:” + password)粗样式
四、请求前置脚本(了解)
介绍:在Pre-request Script页签类编写,在请求发送之前被执行
使用场景
在请求url中需要使用随机数或时间戳
需要对敏感数据进行加密
使用案例
// 生成随机数
var r = Math.random()
console.log(“生成的随机数:”, r)
// 通过全局变量保存随机数
pm.globals.set("g_random", r);
五、Postman关联(重点)
1、 Postman基础介绍
Postman关联:后一个接口的请求需要依赖前一个接口的响应数据,一般通过全局变量或者环境变量来进行参数在接口之间的传递。
技术实现
2、 通过全局变量进行接口关联
案例1:
1.请求获取天气接口,http://www.weather.com.cn/data/sk/101010100.html
2.获取天气接口返回结果中的城市名称
3.请求百度搜索接口:http://www.baidu.com/s?wd={{城市名称}},城市名称即为天气接口获取并保存 到全局变量中的数据。
**代码实现:**
//获取json响应
var jsonData = pm.response.json()
//响应值保存到city
var city = jsonData.weatherinfo.city
//保存天气接口的城市名称—全局变量
pm.globals.set(“g_city”,city);
一、批量执行测试用例(掌握)
二、读取外部文件实现参数化(理解)
使用场景:针对单个接口、存在大量数据需要批量测试测试情况,我们将数据存放到外部的文件,然后postman通过读取外部文件来逐行执行脚本。
案例:
需求:批量查询手机号归属地和所属运营商信息,并校验运营商数据是否正确
接口地址: http://cx.shouji.360.cn/phonearea.php?number=13012345678
部分测试数据:
手机号: 13012345678 运营商: 联通
手机号: 13800001111 运营商: 移动
手机号: 18966778899 运营商: 电信
常见数据格式
csv
json
操作步骤
1. 准备测试数据文件
2. 设置参数
1. 在请求中使用时,直接通过{{变量名}}引用
2. 在断言中使用时,需要借助postman内置的data方法来进行使用,如 data.username
3. 选择数据文件进行批量执行
4. 结果检查
postman生成测试报告首先要安装node.js 、newman 、newman-reporter-html
2、 Postman导出测试集、环境变量、全局变量
2.1 导出测试集
2.2 导出环境变量
2.3 导出全局变量
2.4 将数据文件、测试集、环境变量、全局变量放在一个文件夹下
再该文件夹下 cmd
newman run 测试脚本文件 -e 环境变量文件 -g 全局变量文件 -d 测试数据文件 -r html
– reporter-html-export report.html
参数详解
run 测试脚本文件:表示要执行的postman脚本,及导出的测试集
-e 环境变量文件:指定脚本中依赖的环境变量文件的路径
-g 全局变量文件:指定脚本中依赖的全局变量文件的路径
-d 测试数据文件:指定脚本中依赖的测试数据文件的路径
多接口实现依据
数据库的介绍pyMySQL
一、数据库介绍
概念:一个存放数据的仓库(Database),这个仓库按照一定的数据结构组织、存放、管理数据。
分类:
关系型数据库:mysql、sql server、oracle、DB2等
非关系型数据库:redis等
python操作数据库的方式
pymysql:纯python开发,支持python2和python3,简单易用
二、数据库基本操作
1、安装
安装: pip install PyMySQL
验证: pip show PyMySQL
2、操作流程(重点)
1. 创建连接
2. 获取游标
3. 执行sql
1. 查询操作(select)
2. 非查询操作(insert/update/delete)
3. 事务提交(连接对象.commit())
4. 事务回滚(连接对象.rollback())
4. 关闭游标
5. 关闭连接
什么是游标?(了解)
游标是SQL 的一种数据访问机制 ,游标是一种处理数据的方法。
众所周知,使用SQL的select查询操作返回的结果是一个包含一行或者是多行的数据集,如果
我们要对查询的结果再进行查询,比如(查看结果的第一行、下一行、最后一行、前十行等
等操作)简单的通过select语句是无法完成的,因为这时候索要查询的结果不是数据表,而是
已经查询出来的结果集。
游标就是针对这种情况而出现的。
我们可以将“ 游标 ”简单的看成是结果集的一个指针,可以根据需要在结果集上面来回滚动,
浏览我需要的数据
3、数据准备
CREATE DATABASE if not EXISTS books DEFAULT charset utf8; use books; Drop TABLE if EXISTS `t_book`; CREATE TABLE `t_book`( `id` int(11) not null auto_increment, `title` VARCHAR(20) not NULL COMMENT '图书名称', `pub_date` date not NULL COMMENT '发布日期', `read` int(11) not null default '0' comment '阅读量', `comment` int(11) not null default '0' comment '评论量', `is_delete` TINYINT(1) not NULL DEFAULT '0' COMMENT '逻辑删除', PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='图书表'; INSERT into `t_book` VALUES ('1','射雕英雄传','1980-05-01','12','34','0'); INSERT into `t_book` VALUES ('2','天龙八部','1986-07-24','36','40','0'); INSERT into `t_book` VALUES ('3','笑傲江湖','1995-12-24','20','80','0'); Drop TABLE if EXISTS `t_hero`; CREATE TABLE `t_hero`( `id` int(11) not null auto_increment, `name` VARCHAR(20) not NULL COMMENT '姓名', `gender` SMALLINT(6) not NULL COMMENT '性别', `description` VARCHAR(200) default NULL comment '描述', `is_delete` TINYINT(1) not NULL DEFAULT '0' COMMENT '逻辑删除', `book_id` int(11) not null comment '所属图书ID', PRIMARY KEY(`id`), key `t_hero_book_id`(`book_id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='英雄人物表'; INSERT into `t_hero` VALUES ('1','郭靖','1','降龙十八掌','0','1'); INSERT into `t_hero` VALUES ('2','黄蓉','0','打狗棍法','0','1'); INSERT into `t_hero` VALUES ('3','乔峰','1','降龙十八掌','0','2'); INSERT into `t_hero` VALUES ('4','令狐冲','1','独孤九剑','0','3');INSERT into `t_hero` VALUES ('5','任盈盈','0','弹琴','0','3');
注意事项:
直接使用本地localhost数据库即可
- 请先通过phpstudy启动本地的数据库
- 然后通过Navicat连接本地数据库
- 执行数据库初始化语句
4、数据库基本操作
4.1 连接数据库
4.2 数据库查询操作
1).连接到数据库(host:localhost user:root password:root database:books)
2).获取数据库服务器版本信息
# 导包
import pymysql
# 创建链接
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password='123456',
database="books")
# 获取游标
cursor = conn.cursor()
# 执行SQL
cursor.execute("select version()")
result = cursor.fetchall()
print(result)
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
注意 运行时出现
TypeError: object supporting the buffer API required 密码格式出问题可以选择将settings.py中数据库的密码改成字符串格式或者密码加引号
4.2 数据库查询操作
1).连接到数据库(host:localhost user:root password:root database:books)
2).查询图书表的数据(包括:图书id、图书名称、阅读量、评论量)
3).获取查询结果的总记录数
4).获取查询结果的第一条数据 5).获取全部的查询结果
# 导包
import pymysql
# 创建连接
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password='123456',
database="books")
# 获取游标
cursor=conn.cursor()
# 执行sql
# 2.查询图书表的数据(包括:图书id、图书名称、阅读量、评论量)
sql="select id, title, `read`, `comment` from t_book;"
cursor.execute(sql)
# 3.获取查询结果的总记录数
print(cursor.rowcount)
# 4).获取查询结果的第一条数据
print(cursor.fetchone())
# 5).获取全部的查询结果
# 游标重置为零
cursor.rownumber=0
print(cursor.fetchall())
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
4.3 数据库插入操作
1).连接到数据库(host:localhost user:root password:root database:books autocommit:True)
2).新增一条图书数据(id:4 title:西游记 pub_date:1986/01/01 )
# 导包
import pymysql
# 创建连接
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password='123456',
database="books",
autocommit='ture')
# 获取游标
cursor=conn.cursor()
# 执行sql
# 新增一条图书数据(id:4 title:西游记 pub_date:1986-01-01 )
sql = "insert into t_book(id, title, pub_date) values(5, '西游记', '1986/01/01');"
cursor.execute(sql)
# 3).获取受影响的结果记录数
print("影响的结果记录数为:", cursor.rowcount)
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
4.4 数据库更新操作
1).连接到数据库(host:localhost user:root password:root database:books autocommit:True)
2).更新[西游记]图书名称为(title:东游记)
# 导包
import pymysql
# 创建连接
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password='123456',
database="books",
autocommit='ture')
# 获取游标
cursor=conn.cursor()
# 执行sql
# update t_book set title='东游记' where title = '西游记';
sql = "update t_book set title='东游记' where title = '西游记';"
cursor.execute(sql)
# 3).获取受影响的结果记录数
print("影响的结果记录数为:", cursor.rowcount)
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
4.5 数据库删除操作
# 导包
import pymysql
# 创建连接
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password='123456',
database="books",
autocommit='ture')
# 获取游标
cursor=conn.cursor()
# 执行sql
# 删除图书(title:东游记)
sql = "delete from t_book where title = '东游记';"
cursor.execute(sql)
# 3).获取受影响的结果记录数
print("影响的结果记录数为:", cursor.rowcount)
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
查询与非查询(插入、更新、删除)操作小结:
相同点:基本操作流程是一样
创建连接
获取游标
执行sql
关闭游标
关闭连接
不同点
要执行sql语句不一样
非查询操作需要开启事务(在创建连接时,指定参数autocommit=True)
三、数据库事务操作
引入案例
1).连接到数据库(host:localhost user:root password:root database:books), 并开启自动提交事务
2).新增一条图书数据(id:4 title:西游记 pub_date:1986-01-01 )
3).故意抛出一个异常(模拟代码出现异常)
4).新增一条英雄人物数据(name:孙悟空 gender:1 book_id:4)
""" 1).连接到数据库(host:localhost user:root password:root database:books), 并开启自动提交事务
2).新增一条图书数据(id:4 title:西游记 pub_date:1986-01-01 )
3).故意抛出一个异常(模拟代码出现异常)
4).新增一条英雄人物数据(name:孙悟空 gender:1 book_id:4) """
# 导包
import pymysql
# 创建连接
conn = pymysql.connect(host="localhost",
port=3306, user="root",
password="root",
database="books",
autocommit=True)
# 获取游标
cursor = conn.cursor()
# 执行sql
sql = "insert into t_book(id, title, pub_date) values(4, '西游记', '1986-01- 01');" cursor.execute(sql)
print(cursor.rowcount)
print("-" * 200)
# 主动抛出异常
raise Exception("程序出错啦。。。。。。")
# 4).新增一条英雄人物数据(name:孙悟空 gender:1 book_id:4)
sql = "insert into t_hero(name,gender,book_id) values('孙悟空', 1, 4)"
cursor.execute(sql)
print(cursor.rowcount)
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
概念【理解】
基于代码的角度:一段实现了具体业务单元功能的代码,这段代码要么都执行,要么都不执行
基于业务的角度:最小的业务单元,要么都成功,要么都失败
特点【了解】ACID
原子性:事务中的一系列操作、他是最基本的工作单元。
一致性:在数据库看到的结果要么是执行之前的结果,要么是执行之后的结果。
隔离性:事务的内部状态对其他事务是不可见的。
持久性:通过事务对数据库中数据做的改变,永久有效。
操作【理解】
自动提交(不推荐): autocommit=True
手动提交(推荐):
提交事务: conn.commit()
回滚事务: conn.rollback()
解决导入案例中的问题:数据不一致性问题
1).连接到数据库(host:localhost user:root password:root database:books), 并开启自动提交事务
2).新增一条图书数据(id:4 title:西游记 pub_date:1986-01-01 )
3).故意抛出一个异常(模拟代码出现异常)
4).新增一条英雄人物数据(name:孙悟空 gender:1 book_id:4)
思路:
1.导包
try:
程序前期,需要执行的代码
2.创建连接对象
3.获取游标对象
4.执行sql
+ 在图书表中插入一行数据
+ 主动抛出异常
+ 在英雄人物表中插入一行数据
调用提交事务:conn.commit()
except:
程序出现异常后,处理代码
调用事务回滚:conn.rollback()
finally:
程序结束时,需要执行的代码
5.关闭游标
6.关闭连接
代码实现:
""" 1).连接到数据库(host:localhost user:root password:root database:books), 并开启自动提交事务
2).新增一条图书数据(id:4 title:西游记 pub_date:1986-01-01 )
3).故意抛出一个异常(模拟代码出现异常)
4).新增一条英雄人物数据(name:孙悟空 gender:1 book_id:4) """
# 导包
import pymysql
# 创建连接
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password="root",
database="books",
autocommit=True)
# 获取游标
cursor = conn.cursor()
# 执行sql
try:
sql = "insert into t_book(id, title, pub_date) values(4, '西游记', '1986-01- 01');"
cursor.execute(sql)
print(cursor.rowcount)
print("-" * 200)
# 主动抛出异常
raise Exception("程序出错啦。。。。。。")
# 4).新增一条英雄人物数据(name:孙悟空 gender:1 book_id:4)
sql = "insert into t_hero(name,gender,book_id) values('孙悟空', 1, 4)"
cursor.execute(sql)
print(cursor.rowcount)
# 提交事务
conn.commit()
except Exception as e :
# 回滚数据
conn.rollback()
# 打印异常信息
print(e)
finally:
# 关闭游标
if cursor:
cursor.close()
# 关闭连接
if conn:
conn.close()
四、数据库工具封装
需求
需求分析:
1. sql = "select * from t_book"
2. 调用数据库工具方法
result = exe_sql(sql)
print("结果:", result)
封装
# 导包
import pymysql
# 创建工具类
class DBUtil():
# 初始化
__conn = None
__cursor = None
# 创建连接
@classmethod
def __get_conn(cls):
if cls.__conn is None:
cls.__conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password="root",
database="books")
return cls.__conn
# 获取游标
@classmethod
def __get_cursor(cls):
if cls.__cursor is None:
cls.__cursor = cls.__get_conn().cursor()
return cls.__cursor
# 执行sql
@classmethod
def exe_sql(cls, sql):
try:
# 获取游标对象
cursor = cls.__get_cursor()
# 调用游标对象的execute方法,执行sql
cursor.execute(sql)
# 如果是查询
if sql.split()[0].lower() == "select":
# 返回所有数据
return cursor.fetchall()
# 否则:
else:
# 提交事务
cls.__conn.commit()
# 返回受影响的行数
return cursor.rowcount
except Exception as e:
# 事务回滚
cls.__conn.rollback()
# 打印异常信息
print(e)
finally:
# 关闭游标
cls.__close_cursor()
# 关闭连接
cls.__close_conn()
# 关闭游标
@classmethod
def __close_cursor(cls):
if cls.__cursor:
cls.__cursor.close()
cls.__cursor = None
# 关闭连接
@classmethod
def __close_conn(cls):
if cls.__conn:
cls.__conn.close()
cls.__conn = None
验证代码
from test10_dbutil import DBUtil
# sql = "select * from t_book"
# sql = "insert into t_book(id, title, pub_date) values(4, '西游记', '1986-01-01');"
# sql = "update t_book set title='东游记' where title = '西游记';"
sql = "delete from t_book where title = '东游记';"
result = DBUtil.exe_sql(sql)
print(result)
整体框架
导包
创建工具类
1、创建连接
2、创建游标
3、执行sql
try:
# 获取游标对象
# 调用游标对象.execute(sql)
# 如果是 查询:
# 返回所有数据
# 否则:
# 提交事务 # 返回受影响的行数
except:
# 回滚事务
# 抛出异常
finally:
# 关闭游标
# 关闭连接
4、关闭游标
5、关闭连接