视频教程传送门
12、Pytest接口自动化之request模块返回的response对象详解_哔哩哔哩_bilibili
requests是用来发送http请求以及接收http响应的第三方库,主要用于接口自动化测试
pip install requests
PyCharm 快捷键Alt+Enter 自动导包
目录
data和json传参的区别:主要是通过请求头Content-Type来区分
一、requests库常用的方法
requests.get(url, params=None, **kwargs) | 发送get请求 url是请求路径,params传递参数 |
requests.post(url, data=None, json=None, **kwargs) | 发送post请求 url是请求路径,data传递参数,json传递参数 |
requests.put(url, data=None, **kwargs) | 发送put请求 |
requests.delete(url, **kwargs) | 发送delete请求 |
requests.request(method, url, **kwargs) | 发送所有请求,是所有请求的底层方法,会调用:session.request() |
1.requests.get()
import requests
class TestRequest:
#get请求:获取接口统一鉴权码token接口
def test_get_token(self):
url = "https://api.xxx.com/token"
data ={
#待传参数查看API文档
"grant_type":"client_credential",
"appid":"xxx"
"secret":"xxx"
}
res = requests.get(url=url,params=data)
print(res.json())
if __name__ == '__main__':
TestRequest().test_get_token()
2.requests.post()
会用到上述 test_get_token 获取token, 定义一个全局变量access_token存放获取的token
import requests
class TestRequest:
#全局变量,类变量,通过类名调用
access_token= ""
#get请求:获取接口统一鉴权码token接口
def test_get_token(self):
……
TestRequest.access_token = res.json()['access_token']
#post请求:编辑标签接口
def test_edit_flag(self):
url = "https://api.xxx.com/xxx/update?access_token=" + TestRequest.access_token
data = {
#参数格式查看API文档
"tag":{"id":"xxx","name":"xxx"}
}
res = requests.post(url=url,json=data)
print(res.json())
if __name__ == '__main__':
TestRequest().test_get_token()
TestRequest().test_edit_flag()
说明:上述 res = requests.post(url=url,json=data) 中 json 改为 data会报错
四种传参方式对应的Content-Type
Content-Type: 是服务器要求传入的报文的内容类型
请求:请求方式、请求路径、请求头、请求正文
postman四种传参方式对应的Content-Type的值如下
form-data | Content-Type:multipart/form-data | |
x-www-form-urlencoded | Content-Type:application/x-www-form-urlencoded | |
raw | text | Content-Type:text/plain |
javascript | Content-Type:application/javascript | |
json | Content-Type:application/json | |
html | Content-Type:text/html | |
xml | Content-Type:application/xml | |
binary | Content-Type:application/octet-stream |
参数说明:
(1)请求的参数是:form-data,代表这是表单传参或者文件上传。type=file
Content-Type:multipart/form-data;
(2)请求的参数是:x-www-form-urlencoded,代表这是表单传参。(k1=v1&k2=v2)
Content-Type:application/x-www-form-urlencoded(data传参)
(3)请求的参数是:raw,代表原始格式传参。
text:Content-Type:text/plain(data传参)
javascript:Content-Type:application/javascript
json:Content-Type:application/json(json传参)
html:Content-Type:text/html
xml:Content-Type:application/xml
(4)请求的参数是:binary,代表原始格式传参。
Content-Type:application/octet-stream
data和json传参的区别:主要是通过请求头Content-Type来区分
data和json传参以及Content-Type的关系如下:
(1)data传参:报文是dict类型 -> Content-Type:application/x-www-form-urlencoded
报文是str类型 -> Content-Type:text/plain
(2)json传参:报文可以是dict也可以是str -> Content-Type:application/json
data 可以传键值对,即非嵌套的dict,例如{key1:value1,key2:value2},也可以传str格式
json 可以传任何形式的dict(包括嵌套的dict)
json.loads() 把json字符串转化成dict形式
json.dumps() 把dict格式转化成json字符串
例如,上面的edit的例子,也可以改成如下,不会报错
str_data = json.dumps(data)
res = requests.post(url=url,data=str_data)
#post请求:编辑标签接口
def test_edit_flag(self):
url = "https://api.xxx.com/xxx/update?access_token=" + TestRequest.access_token
data = {
#参数格式查看API文档
"tag":{"id":"xxx","name":"xxx"}
}
str_data = json.dumps(data)
res = requests.post(url=url,data=str_data)
print(res.json())
文件上传
#文件上传
def test_file_upload(self):
url = "https://api.xxx.com/xxx/uploading?access_token=" + TestRequest.access_token"
data = {
"media":open(r"D:\star.png","rb")
}
res = requests.request("post",url=url,files=data)
print(res.json())
3.requests.request()
get/post/put/delete 都是调用requests.request方法,后者调用 session.request方法
method | 请求方式 |
url | 请求路径 |
params=None | get方式传参 |
data=None | post/put方式传参 |
json=None | post方式传参 |
headers=None | 请求头 |
cookies=None | 请求cookie |
files=None | 文件上传 |
auth=None | 鉴权 |
timeout=None | 超时 |
allow_redirects=True | 是否允许重定向 |
proxies=None | 设置代理 |
hooks=None | 在请求得到响应后的自定义操作 |
stream=None | 文件下载 |
verify=None | ssh认证 |
cert=None | CA证书 |
requests.session() | 创建会话对象 |
二、requests模块返回的response对象
res.json() | 获得返回的字典格式的数据 |
res.text | 获得返回的字符串格式的数据 |
res.content | 获得返回的bytes字节类型的数据 |
res.status_code | 返回状态码 |
res.reason | 返回状态信息 |
res.cookies | 返回cookie信息 |
res.encoding | 返回编码格式 |
res.headers | 返回响应头 |
res.request.xxx | 返回请求的数据,如:请求头、请求参数 |
三、请求必须带请求头的接口
需要取到 res.text中,csrf_token的值,使用正则匹配
<input type="hidden" name="csrf_token" value="xxxxx">
requests.request() 中传入参数headers
……
#加一个全局变量
csrf_token = ""
#访问首页接口
def test_start(self):
url = "http://xxx"
res = requests.request(method="get",url=url)
print(res.json())
#正则提取,".*?"非贪婪模式、最小匹配
obj = re.search('name="csrf_token" value="(.*?)"',res.text)
TestRequest.csrf_token = obj.group(1)
#登录接口
def test_login(self):
url = "http://xxx"
data = {
"username": "xxx",
"password": "xxx",
"csrf_token": TestRequest.csrf_token
}
headers = {
#根据接口文档写
"Accept": "xxx",
"X-Requested-With": "XMLHttpRequest"
}
res = requests.request(method="post",url=url,data=data,headers=headers)
print(res.json())
……
四、需要cookie鉴权和session鉴权的接口
上述还不好使,打开浏览器控制台,查看Cookies
90%以上的基于web的接口都有cookie鉴权
两种解决方式:使用cookie关联、使用session关联
1.使用cookie关联
#新增全局变量
php_cookie = ""
#访问首页接口
def test_start(self):
...
#提取Cookie
TestRequest.php_cookie = res.cookies
#登录接口
def test_login(self):
...
res = requests.request(method="post",url=url,data=data,headers=headers,cookies=TestRequest.php_cookie)
print(res.json())
2.使用session关联
#新增全局变量
sess = requests.session()
#访问首页接口
def test_start(self):
...
res = TestRequest.sess.request(method="get",url=url)
...
#登录接口
def test_login(self):
...
res = TestRequest.sess.request(method="post",url=url,data=data,headers=headers)
...