用Python做接口测试(一)request相关知识
1、什么是requests
1.1requests请求介绍
requests代表是请求,在python当中是一个库 让HTTP服务人类
1.2requests库的安装
pip3 install requests
1.3用Python代码处理get请求
import requests api=requests.get( url='http://**.**.***.***:*****/login/auth/', params={"name":"jiachao"}) #协议状态码 print('协议状态码:',api.status_code) #获取请求地址 print(api.url) #响应数据 print('返回字符串:',api.text) print('返回⼆进制的内容:',api.content) print('返回的是字典数据类型:',api.json()) #响应头 print('响应头:',api.headers)
在这里面我们需要注意的是,响应数据一般是使用api.text,如果响应数据是JSON格式的 那么使用api.json()
1.4查询电话号码实战
api=requests.get( url='http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo', params={"mobileCode":"1**********","userID":""}) print(api.url) print(api.status_code) print(api.text) print(api.headers)
需要注意的是 在进行get请求的时候 如果请求数据要填写我的话 我们需要在括号内输入params并且填写字典格式(key&value)
1.5用python代码处理JSON数据格式
import json import requests api=requests.post( url='http://**.**.***.***:****/login/auth/', json={"username":"1**********","password":"a*****8"}, headers={"content-type":"application/json"}) print(json.dumps(api.json(),indent=True,ensure_ascii=False))
在输出结果的时候 这里面我们对代码进行解析
参数介绍
json.dumps是进行序列化
api.json为以json的方式写入
indent=true 是进行初始化
ensure_ascii=False 是不用阿斯克码编码 (用来处理中文乱码)
1.5.1data和json的区别
什么时候使用json?
当请求参数JSON的时候使用json的参数
当请求参数是json,但是要使用data的参数,那么请求参数要进行序列化的处理
什么时候使用data?
当请求参数是表单的时候使用data
当请求参数是json格式的时候,那么请求参数要进行序列化的处理
1.6用python代码处理表单数据格式
api=requests.post( url='http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo', data={"mobileCode":"1**********","userID":""}, headers={"content-type":"application/x-www-form-urlencoded"}) print(api.text)
处理表单格式和处理json请求不同的点就是在我们写conetnt-type的时候 要写入表单数据类型即可
1.7关于复杂表单格式的实战解析
api=requests.post( url='https://www.lagou.com/jobs/v2/positionAjax.json', data= {"data":"7Xx8%2BncjEMSVaVAgnRvUNTUE96%2BZQ2vPzFNSpQ88YRMH6wPSJ8i6Cprv9zK8LdkaMCryRC4KsX IeYziVgSmqOpzWRJLTICaDRADfVKega8j0HtL4PbSKAbU2Bu%2BELgYZ9P0eVN9ha0eAJYfBfoMUbuAmQzuFErA 7fLqd2E56hwfw5%2BNRba2bvdD0Dh3cTl%2FIM4NkMRF%2FGcXEvDJWAVWGYKUh%2FSEpM0WJNhhSM0dXB6%2BR 51Ln0ngfo2LEYJKwjMJh"}, headers={ "content-type":"application/x-www-form-urlencoded; charset=UTF-8", "user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", "cookie":"根据network获取", "referer":"根据network获取"}) print(api.status_code) print(json.dumps(api.json(),indent=True,ensure_ascii=False))
以上个人已编写好的代码
1.7.1代码解析
本次测试案例为拉勾网
在上述代码中 我们可以看到 相比于以往的表单格式 比较复杂 其实总结起来无非是几点
1、url地址:
2、请求数据 : 因为这次我们这次通过network 获取到了请求数据 直接复制粘贴就可以
3、请求头 :在唱过的操作中 其实用到的请求头 在业界最常用的 必须要带的四个请求头分别为 conetnt-type ,user-agent ,cookie,referer 依次进行添加即可
然后我们输出该请求url的协议状态码 和响应数据
1.8用python处理动态参数
因为我们在处理session的请求的时候 会存在动态参数
设想一个场景,我们输入用户名和密码提供给服务端,此时服务端回返回给我们一个随机的sessionID 那么应该按照如下方式处理
def login(): api=requests.post( url='http://**.**.***.***:****/login/auth/', json={"username":"13********","password":"*****8"}, headers={"content-type":"application/json"}) return api.json()['token'] def index(): api=requests.get( url='http://47.95.142.233:8000/interface/index', headers={"Authorization":"JWT {token}".format(token=login())}) print(api.text) assert api.json()['count']['api']==4
1.8.1代码解析
1、我们定义两个函数 分别为login 和index 其中login为登录的网页 index为登录成功后返回的网页
2、在我们输入相应的用户名和密码 通过return.api.json["token"]来将token返回给login函数 以被调用
3、在我们写index的函数时候 在请求头需要写入 "Authorization":"JWT {token}".format(token=login())来进行调用全局变量token的值 才能获得 登录成功后返回的响应数据
.4、在结尾我们根据python源生的断言 assert r.json()["count"]["api"]==4来验证返回的数据是否正确 如正确 则可以证明我们获得了返回的响应数据
1.9用python代码来处理cookie请求
在请求头里面需要带上服务端的响应头中来返回的set-cookie的值 用到的关键词为cookies
1.9.1实战案例代码
import requests def login(): api=requests.post(url="https://home.51cto.com/index?reback=https%3A%2F%2Fedu.51cto.com%2Fcenter%2Fuser%2Findex%2Flogin-success%3Fsign%3D0b8cAQcICQgAUwNSB1cKAwIKXFJUV1UAC1NTAlBcQRVIFwseGF1dTR5WAgFDXRxSDF8XV1IPFwNBHVRfEUZGBBcRQlRFF15dRE5AFkJWSxwAXU1GRARTBAtR%26client%3Dweb&iframe=0&is_go_to_user_set_mobile=1", data={"_csrf":"b0tpNzY0NVIeAyNZG05dZCooP297eEMUBihcTw59QgUkezpPBV9GNQ==", "LoginForm[username]":"1******", "LoginForm[password]":"a******", "show_qr":"0"}, headers={"content-Type":"application/x-www-form-urlencoded", "cookie":"acw_tc=2760826216425816925208847e7858ddd405cdc867fa071cec17c576a4cb7a; PHPSESSID=1tm0ep6qmvavbtvc02edps63u3; _csrf=8bd4e0bb9d580c84ad72c0878787c487e915a6afdf434b9ab2121637ac6f6025a%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22qHJn-zh6EcVXMLvFic5x8IwWK0Sx3ksg%22%3B%7D; _uab_collina=164258160896132940103325; _ourplusFirstTime=122-1-19-16-40-8; _ourplusReturnCount=1; _ourplusReturnTime=122-1-19-16-40-8; www51cto=C9BA92B0E626A5F0007CD254829BC978aiYz; sajssdk_2015_cross_new_user=1; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217e717e4aec9-03a8b5f43617fb-f791b31-1440000-17e717e4aed998%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%2217e717e4aec9-03a8b5f43617fb-f791b31-1440000-17e717e4aed998%22%7D; login_from=edu.51cto.com; reg_from=edu.51cto.com; Hm_lvt_844390da7774b6a92b34d40f8e16f5ac=1642581609; Hm_lpvt_844390da7774b6a92b34d40f8e16f5ac=1642581609", "referer":"https://home.51cto.com/index?reback=https%3A%2F%2Fedu.51cto.com%2Fcenter%2Fuser%2Findex%2Flogin-success%3Fsign%3D0b8cAQcICQgAUwNSB1cKAwIKXFJUV1UAC1NTAlBcQRVIFwseGF1dTR5WAgFDXRxSDF8XV1IPFwNBHVRfEUZGBBcRQlRFF15dRE5AFkJWSxwAXU1GRARTBAtR%26client%3Dweb&iframe=0&is_go_to_user_set_mobile=1", "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"}) print(api.text) print(api.status_code) print(api.cookies) return api.cookies def profile(): api=requests.get(url="https://edu.51cto.com/center/user/info/get-user-info", cookies=login()) print(api.status_code) print(api.text) profile()
因代码比较繁琐 所以如下图所示来展示逻辑关系
1.10Python处理接口测试的timeout参数含义
因为有的时候服务器响应数据很慢,有时候很快,所以这个时候需要添加timeout
还有一种就是网络请求出现requests.exceptions.ConnectTimeout的错误时候,就可以添加timeout了
1.10.1代码详情演示
import requests from requests.auth import HTTPBasicAuth api=requests.get(url="http://***.***.***.*/v1/api/books", auth=HTTPBasicAuth(username="ad***n",password="a****n"), timeout=180) print(api.status_code) print(json.dumps(api.json(),indent=True,ensure_ascii=False))
其实timeout对于我们之前学的UI自动化测试来说 可以和隐形等待来画===
即为限制等待的最大时长,如果超过这个时间(秒)还没有获取到响应数据 则弹出timeout进行报错
1.11Python处理接口测试的auth参数含义
当如果我们进行测试的时候 提示协议状态码为403 这个时候 就是证明的有权限但是禁止访问,可以理解成我们需要用户名和密码登录成功后才能进行访问
这个时候就要用到requests库里面的 HTTPBasicAuth方法了
具体使用方法如下
import requests from requests.auth import HTTPBasicAuth api=requests.get( url='http://1**.**.***.***:****/v1/api/books', auth=HTTPBasicAuth(username="admin",password='admin')) print(api.status_code) print(api.json())
我们通过auth参数 来进行定义用户名和密码 使得可以获得权限来进行访问内容
1.12Pyhon处理接口测试的verify参数含义
在现实的工作场景
当我们的代码没有任何问题,但是请求就是返回ssl以及403的问题,那么久意味着需要设置verify的参数
如返回错误:requests.exceptions.SSLError 这个时候我们就需要带上verify参数
具体使用方法如下
api=requests.get( url='https://***.**.***.***:****/v1/api/books', auth=HTTPBasicAuth(username="admin",password='admin'), timeout=180,verify=False) print(api.status_code) print(api.json())
我们需要在添加参数verify=False即可