目录:导读
前言
1、token令牌
token:
令牌(令牌代表身份信息,身份标识----身份校验(数据库db校验,每发个请求就需要校验很麻烦,避免频繁访问数据库,token就表示身份))
cookie和token(cookie里面最关键的就是session id值)
cookie里面有时候有sessionid和token值
一般为了减少对数据库的访问,校验,数据库的账号密码
做个令牌:token需要身份校验,账号密码校验,获取token值(返回token字符串))
token也是由服务器参数的,存在服务器的内存或者硬盘中
有一套产生规则,会涉及到加密算法
用token来实现登录:
开发提供一个获取token接口,根据用户名+密码,获取一个token值–返回一个token(字符串)
token值服务器通过什么发给客户端:
通过响应头传给客户端 次要
通过响应消息体传给客户端 主要
通过cookie传递给客户端 很少
token使用场景:
服务器访问的同时,vip学员访问服务器,怎么保证vip学员的权限,普通用户也能访问,vip学员的访问的时候加一个验证,vip访问的同时加个验证,
访问网站同时校验身份,必须去vip官网去认证,通过vip账号密码拿到token值,去访问服务器时候时候token带上。
做二次校验,身份的校验,不是每个人都能访问这个网站,只有vip学员才可以,访问之前vip学员拿vip账号去网站认证一下,获取到token值然后每次访问都带上这个token就可以了。
这个token可以在cookie里面,token放头headers里面和cookie里面都可以,这时候token值,cookie里面自行加token值,自行组装
额外增加某些校验参数,cookie里面可以加一些值,如token值,自行封装cookie
认证的时候token身份二次校验,token放cookie里面和头里面都行(校验是不是vip学员)
2、接口测试数据格式
1)接口自动化测试数据源(测试用例来源哪里)测试用例一般存放在哪里
excel测试用例
yaml格式用例
csv
2)自动化脚本中的数据类型:
表单格式:
[urlencoded格式]:又叫form格式,或者是x-www-form-urlencoded格式(type类型为表单形式,传数据表单形式)
表单格式是键值对组成的,键和值之间用=,多个值之间用& 如:name=zhengsan&age=16
json格式(str字符串:键值对类型的字符串)
json有对象,数组两种结构,有字符串,数字,逻辑值,空值四种数据类型
用大括号{}表示对象,对象由属性组成的,属性由键值对组成的,键和值用冒号隔开,属性之间用逗号隔开,键必须用双引号引起来
用中括号[]表示数组,数组由单独的值组成
json灵活,json可以嵌套
3、json格式详解
对象:大括号表示,对象由属性组成,属性由键值对组成,键和值对之间用冒号隔开,属性之间用逗号隔开,另外键必须双引号
{“姓名”:“姚明”,“年龄”:38}
数组:用中括号表示
["小明","小李","小百"]
[{"姓名":"姚明","年龄":38}]
嵌套:对象中可以再嵌套对象和数组
{"姓名":"姚明","年龄":38,"家禽":["小明","小李","小百"]}
4、了解教管系统:(在线管理系统)(前后端分离的) 什么框架,什么配置
项目描述:
教师管理系统是一款在线管理学生课程的一款软件
主要功能包括:
课程:包含了所有课程名和课程详情
老师:可以查看老师姓名,授课内容及授课班级
学生:包括班级号,班级包含课程,所属学生和班级学生进度
框架结构:
后端架构:cherrypy与django结合
diango:包含了所有的课程名和课程详情
cherrypy:使用cherrypy作为diango的development server
数据库:sqlite
前端:html,js,css
5、python自动化过程中配置文件格式
配置文件格式:text(很少用),cnf,ini,yaml,excel(很少用),.py也可以
6、requests.post方法:data和json参数区别(重点)
1)params参数
如果传入的是字典,自动编码为表单,针对的是get方法,
一般get请求需要---def get(url, params=None, **kwargs):
----只有get请求传有params,其他请求没有‘
2)data参数
如果传入是字典,自动编码为表单形式传递, 针对的是post/put方法
3)data参数
如果传入的是字符串,按原格式直接发布出去 针对的是post/put方法
4)json参数
如果传入的是字典,自动编码为json字符串 针对的是post/put方法
5)json格式
如果传入的是字符串,按原格式基础上添加双引号发布出去 针对的是post/put方法
6)headers参数
传递的是字典格式,针对的是所有方法
data=json.dumps(dictpayload)等同于json=dictpayload
dictpayload是一个字典
(data=payload)所以data和json传递数据最好以字典形式去做,payload请求体最好构建成字典,也可以构建成字符串,看具体情况,用data还是json取决接口本身的type类型)
7、request库的使用,查看请求信息和响应信息,设置编码等
r.status_code # 得到响应状态码
r.headers # 打印出响应头,获取一个字典
r.cookies # 获取cookies
reps.text # 打印响应体
reps.json() # 查看响应体,返回一个json格式
r.request.headers # 打印请求头
r.request.body # 打印请求体
reps.encoding="unicode_escape" # 编码设置,为了看到中文(设置响应的编码格式)
8、cookie值的获取和传递操作实战
1)直接获取cookie对象操作,如果不需要对cookie进行任何操作封装直接这样取值
reps.cookies
获取的是一个cookie对象,不能改
在login函数里面把reps.cookies获取到的的cookie对象return返回出去给调用的函数使用
外面拿到这个cookie对象后直接cookies=cookie这样传递就行,不需要二次封装
reps=requests.post(lesson_url,data=payload,cookies=cookie)
import requests
import json
from api接口自动化.teachTest.config import HOST
def login(inData):
url = f"{HOST}/api/mgr/loginReq"
header = {"Content-Typ": "application/x-www-form-urlencoded"} #表单传递
payload = inData #后面账号密码可能变化,写成参数
reps = requests.post(url, data=payload, headers=header)
reps.encoding = 'unicode_escape'
return reps.cookies #直接可以取响应的cookie对象,
#return reps.headers # 返回是个字典
#return reps.headers['Set-Cookie'] #返回:sessionid=twenk9lrxixxplrlfqjusmlq6m1dxvfs; HttpOnly; Path=/(返回sessionid=“”)
#return reps.cookies['sessionid'] #通过cookie对象取值sessionid值(cookie对象本身带sessionid的)
#通过cookie对象本身的键取获取sessionid值
if __name__ == '__main__':
res=login({"username":"auto","password":"sdfsdfsdf"})
print(res)
import requests
import json
from api接口自动化.teachTest.config import HOST
from login import login
#cookie值获取了怎么用 cookies=cookie,直接传的cookie对象,cookies=cookie就行,cookie对象传递不需要cookie封装到头
#如果是获取的cookie的值,字符串类型那就需要封装到头
#固定的cookie对象,不需要二次封装,直接取cooke,获取得cookie对象,就可以直接cookies=cookie传递
cookie=login({"username":"auto","password":"sdfsdfsdf"}) #直接获取cookie对象得方法
lesson_url =f"{HOST}/api/mgr/sq_mgr/"
Host = 'http://127.0.0.1:80'
api_url = f'{Host}/api/mgr/sq_mgr/'
header = {'Content-Type': 'application/x-www-form-urlencoded'}
payload={
"action":"add_course",
"data":'{"name":"初中化学01","desc":"初中化学课程","display_idx":"4"}'
}
reps=requests.post(lesson_url,data=payload,cookies=cookie)
reps.encoding = 'unicode_escape'
print(reps.text)
2)通过响应头headers里面的set_cookie获取sessionid值
通过响应头获取cookie里最重要的sessionid来封装cookie,如果cookie需要做二次封装,自带的cooike不够,可以这样做
cookie在响应头里面 a=reps.headers 返回的是一个字典
import requests
import json
from api接口自动化.teachTest.config import HOST
def login(inData):
url = f"{HOST}/api/mgr/loginReq"
header = {"Content-Typ": "application/x-www-form-urlencoded"} #表单传递
payload = inData #后面账号密码可能变化,写成参数
reps = requests.post(url, data=payload, headers=header)
reps.encoding = 'unicode_escape'
return reps.headers['Set-Cookie'] #得到的是一个 sessionid=md31vzd54tvqut8eaxohxl9pjedeujk8; HttpOnly; Path=/这种类型 #后面还要自己转化
3)通过cookie对象获取sessionid值
获取set-cookie的sessionid值或者cookies的sessionid值来自行封装cookie(cookie需要加东西可以这么做),二次封装cookie这样搞,cookie里面最关键的sessionid值取出来需要自行封装cookie。
reps.headers 返回是个字典,我们要的sessionid在set-cookie里面,
login函数return reps.headers[ ‘Set-Cookie’] 得到sessionid=md31vzd54tvqut8eaxohxl9pjedeujk8; HttpOnly; Path=/
return reps.cookies[‘sessionid’] 也能直接获取sessionid的值,
cookie对象本身带sessionid的,通过键本身获取得到:bm2k2n3eyo0r09jpuie8kkcjjd63gzob sessionid的值
取得干净地sessionid值,reps.cookies[‘sessionid’]这种方法最方便,不需要任何处理,
得到sessionid值自己封装cookie:
user_sessionid=login({"username":"auto","password":"sdfsdfsdf"})
user_sessionid=bm2k2n3eyo0r09jpuie8kkcjjd63gzob
获取用户得sessionid值
sessionid一般在cookie里面的,sessionid是cookie得一部分,把user_sessionid值封装成一个cookie
user_cookie={"sessionid":user_sessionid}
这就把cookie封装好了 先获取sessionid然后自行封装的
如果cookie需要加东西,这样直接自己在封装cookie里添加: user_cookie={“sessionid”:user_sessionid,“name”:“ywt”}怎么加都行,灵活,这时候直接发送请求附加自己组装的cookie:
reps=requests.post(lesson_url,data=payload,cookies=user_cookie)
9、token值得获取和传递操作实战
1)获取简单的token,不加密的token(明码的token)
import requests
from random import randint
import json
import pprint # 这个函数只能完美打印字典的数据类型
HOST = "http://47.96.181.17:9090" # 主机地址
# 简单的token,不加密的token(明码的token)
# 1获取token值
def get_token():
token_url = f"{HOST}/rest/toController"
header = {"Content-Type": "application/json"} # 头部字典类型
payload = {"userName": "J201903070064", "password": "362387359"}
reps = requests.post(token_url, json=payload, headers=header)
# pprint.pprint(reps.json()) #字典类型可以使用pprint完美打印
return reps.json()['token']
# 2新增用户
def add_user():
adduser_url = f"{HOST}/rest/ac01CrmController"
token = get_token()
print(token)
header = {"Content-Type": "application/json", "X-AUTH-TOKEN": token}
payload = {"aac003": "张三",
"aac004": "1",
"aac011": "21",
"aac030": f"135{randint(11111111, 99999999)}", # 随机传入号码值
"aac01u": "88002255",
"crm003": "1",
"crm004": "1",
} # 字典类型
# token一般在头部传递,
reps = requests.post(adduser_url, json=payload, headers=header)
return reps.json()
if __name__ == '__main__':
pprint.pprint(add_user())
2)加密的token token加密+上传文件接口
上传文件接口请求头需要Cookie: token=通过获取 token 接口获取(cookie里面放sessionid还是token都可以,看开发和接口文档)
如果判断不了,可以使用fiddler抓个包查看
import requests, json
import hashlib # 这是加密库
def get_md5_data(psw): # MD5加密--password String md5(‘zr’+111111 +‘hg’)
password = f"zr{psw}hg"
md5 = hashlib.md5() #1:创建一个md5对象
md5.update(password.encode("utf-8")) #2:完成加密,updata方法加密 对象.方法(需要加密的对象.encode("utf-8")),加密时候最好设置编码
# 对字符串进行编码后再进行一个加密
# md5(b"zr111111hg") #也可以传二进制数据直接进行编码:如下
# import hashlib
# md5 = hashlib.md5()
# md5.update(b'zr11111111hg')
# print(md5.hexdigest())
# 方法二:一行也可以写
# print(hashlib.md5(b'zr11111111hg')).hexdigest()---这样写也可以,(传bytes类型。可以这么写)
# 3要输出结果,return
return md5.hexdigest()
# 1:获取接口需要的token
HOST = "http://121.41.14.39:2001"
def get_token(inname, inpsw):
token_url = f"{HOST}/token/token" # url
header = {"Content-Type": "application/x-www-form-urlencoded"} # 请求头,封装成字典
# password String md5(‘zr’+111111 +‘hg’)----password需要md5加密
# 打开md5加密网页(百度查询) 把“zr111111hg”加密码提取出来:5c4fcc5add5d087de1e8534189c687f7
# md5加密网站;http://tools.jb51.net/password/CreateMD5Password/
payload = {"mobile": inname, "password": get_md5_data(inpsw)}
reps = requests.post(token_url, data=payload, headers=header)
return reps.json()["data"] # 这里的data就是我们要的token
# 2:文件上传接口
# post方法,文件上传接口,先抓个包
# Content-Type: multipart/form-data; boundary=WebKitFormBoundaryLpsjAVSe95yonybu--文件上传有个随机参数boundary,算法可以做
# 做文件接口一般不带这个type,也不带头,除非真的校验,要去找对应的算法---麻烦(传type会有问题)
# 文件body---
# ------WebKitFormBoundaryLpsjAVSe95yonybu
# Content-Disposition: form-data; name="file"; filename="QQ图片20201009011422.png"
# Content-Type: image/png
# name="file"---你传给那个变量,文件名
# filename="QQ图片20201009011422.png"---文件对象
# Content-Type: image/png 文件类型
# 文件不要写绝对路径(写相对路径)---不然代码移植很麻烦
def file_doUpload():
file_url = f"{HOST}/user/doUpload"
# {变量:(文件名,文件对象,文件的类型)} ----文件对象需要open打开,open函数返回文件对象---文件对象有三个部分
# 文件的打开不能用read,会乱码,只能用rb模式打开,二进制模式打开,读出是bytes字节的
# 传文件的话一般这样做的需要--文件变量(文件对象)--组装好
payload = {"file": ("QQ图片20201009011422.png", open("../data/QQ图片20201009011422.png", "rb"), "jpg/png/gif")}
reps = requests.post(file_url, files=payload)
print(reps.json())
file_doUpload()
10、测试用例的设计
大部分是功能的用例:中文描述很多,用例为人设计,前置条件—步骤–预取结果–实际结果
自动化用例设计不同 用例为代码设计(代码好处理才行) 用例需要数据分离
用例设计需要了解功能,有哪些模块得知道。
最全Python自动化测试进阶之路视频教学 (全集)
下面是我整理的2025年最全的软件测试工程师学习知识架构体系图 |
一、Python编程入门到精通
二、接口自动化项目实战
三、Web自动化项目实战
四、App自动化项目实战
五、一线大厂简历
六、测试开发DevOps体系
七、常用自动化测试工具
八、JMeter性能测试
九、总结(尾部小惊喜)
人生最动人的篇章,往往写在最艰难的转折之后。当你觉得力不从心时,请记住:每一个"不可能"的突破,都始于"再试一次"的勇气。你的坚持,正在为世界书写新的可能!
别让他人的质疑成为你的枷锁!你体内蕴藏着改变命运的力量,每个微小的进步都在为辉煌铺路。当别人停下脚步时,你的坚持就是最有力的回应。向前走,属于你的舞台正等待绽放!