Python接口测试实战1(上)- 接口测试理论
Python接口测试实战1(下)- 接口测试工具的使用
Python接口测试实战2 - 使用Python发送请求
Python接口测试实战3(上)- Python操做数据库
Python接口测试实战3(下)- unittest测试框架
Python接口测试实战4(上) - 接口测试框架实战
Python接口测试实战4(下) - 框架完善:用例基类,用例标签,从新运行上次失败用例
Python接口测试实战5(上) - Git及Jenkins持续集成
Python接口测试实战5(下) - RESTful、Web Service及Mock Serverjavascript
更多学习资料请加添加做者微信:lockingfree获取html
上节课咱们学习了接口测试的理论,抓包工具及使用Postman手工测试各类接口,这节课咱们主要讲解使用Python语言来发送接口请求,实现接口测试自动化。java
发送请求,咱们这里主要使用Python的一个第三方包(须要先安装):requests。
Python3自带的http.client和urllib.request都能发送http请求,不过相对来讲使用较麻烦,第三方库requests让发送请求更简单,支持自动编码解码,会话保持,长连等python
参考: requests官方文档git
pip install requests
,等待安装完成便可pip3 install requests
,等待安装完成便可sudo python3 -m pip install requests
,等待安装完成便可验证是否安装成功:github
打开命令行,输入python
,在python shell环境下输入import requests
没有报错即安装成功算法
发送一个请求分3步:shell
打开Pycharm,新建一个demo项目,项目下新建一个Python文件,输入如下内容:数据库
# 导入requests包 import requests # 1. 组装请求 url = "http://httpbin.org/get" # 这里只有url,字符串格式 # 2. 发送请求,获取响应 res = requests.get(url) # res即返回的响应对象 # 3. 解析响应 print(res.text) # 输出响应的文本
import requests url = "http://www.tuling123.com/openapi/api?key=ec961279f453459b9248f0aeb6600bbe&info=你好" # 参数能够写到url里 res = requests.get(url=url) # 第一个url指get方法的参数,第二个url指上一行咱们定义的接口地址 print(res.text)
或json
import requests url = "http://www.tuling123.com/openapi/api" params = {"key":"ec961279f453459b9248f0aeb6600bbe","info":"你好"} # 字典格式,单独提出来,方便参数的添加修改等操做 res = requests.get(url=url, params=params) print(res.text)
import requests url = "http://httpbin.org/post" data = {"name": "hanzhichao", "age": 18} # Post请求发送的数据,字典格式 res = requests.post(url=url, data=data) # 这里使用post方法,参数和get方法同样 print(res.text)
import requests url = "http://httpbin.org/post" data = '''{ "name": "hanzhichao", "age": 18 }''' # 多行文本, 字符串格式,也能够单行(注意外层有引号,为字符串) data = '{"name": "hanzhichao", "age": 18}' res = requests.post(url=url, data=data) # data支持字典或字符串 print(res.text)
data参数支持字典格式也支持字符串格式,若是是字典格式,requests方法会将其按照默认表单urlencoded格式转换为字符串,若是是字符串则不转化
若是data以字符串格式传输须要遵循如下几点:
通常来讲,建议将data声明为字典格式(方便数据添加修改),而后再用json.dumps()方法把data转换为合法的JSON字符串格式
import requests import json # 使用到JSON中的方法,须要提早导入 url = "http://httpbin.org/post" data = { "name": "hanzhichao", "age": 18 } # 字典格式,方便添加 headers = {"Content-Type":"application/json"} # 严格来讲,咱们须要在请求头里声明咱们发送的格式 res = requests.post(url=url, data=json.dumps(data), headers=headers) # 将字典格式的data变量转换为合法的JSON字符串传给post的data参数 print(res.text)
或直接将字典格式的data数据赋给post方法的JSON参数(会自动将字典格式转为合法的JSON文本并添加headers)
import requests url = "http://openapi.tuling123.com/openapi/api/v2" data = { "reqType":0, "perception": { "inputText": { "text": "附近的酒店" }, "inputImage": { "url": "imageUrl" }, "selfInfo": { "location": { "city": "北京", "province": "北京", "street": "信息路" } } }, "userInfo": { "apiKey": "ec961279f453459b9248f0aeb6600bbe", "userId": "206379" } } res = requests.post(url=url, json=data) # JSON格式的请求,将数据赋给json参数 print(res.text)
练习:
http://www.tuling123.com/openapi/api?key=ec961279f453459b9248f0aeb6600bbe&info=你好
,结合Python的input编写一个机器人聊天室http://openapi.tuling123.com/openapi/api/v2
,封装一个实用的查询方法,查询你附近的美食等等程序中的对象,如Python中的字典、列表、函数、类等,都是存在内存中的,一旦断电就会消失,不方便传递或存储,因此咱们须要将内存中的对象转化为文本或者文件格式,来知足传输和持久化(存储)需求
对象在HTTP中的传输过程
HTTP协议是超文本传输协议,是经过文本或二进制进行传输的,因此咱们发送的请求要转化成文本进行传输,收到的响应也是文本格式,若是是JSON,通常还须要将文本格式从新转化为对象
JSON对象(Python字典) -> 转为文本请求 -> 发送请求
-> 服务器收到文本请求 -> 将文本请求转化为对象,获取其中的参数,处理业务
-> 返回文本格式的响应 -> 客户端转为对象格式来从响应中取值
JSON对象是javascript object即javascript中的对象,是一种通用的格式,格式严格,不支持备注。
JSON文本和JSON对象的区别:
JSON对象是内存中一个对象,拥有属性和方法,能够经过对象获取其中的参数信息
Python中咱们通常提到JSON对象指的是字典
Python的字典的格式和JSON格式,稍有不一样:
import json # 须要导入JSON包 data = {'name': '张三', 'password': '123456', "male": True, "money": None} # 字典格式 str_data = json.dumps(data) # 序列化,转化为合法的JSON文本(方便HTTP传输) print(str_data)
输出:{"name": "\u5f20\u4e09", "password": "123456", "male": true, "money": null}
json.dumps()支持将json文本格式化输出
import requests import json res = requests.post("http://www.tuling123.com/openapi/api?key=ec961279f453459b9248f0aeb6600bbe&info=怎么又是你") print(res.text) # 输出为一行文本 res_dict = res.json() # 将响应转为json对象(字典)等同于`json.loads(res.text)` print(json.dumps(res_dict, indent=2, sort_keys=True, ensure_ascii=False)) # 从新转为文本
看一下输出结果对比:
{"code":100000,"text":"我才要说怎么又是你"} # res.text,有些接口中文会返回为\u.. { "code": 100000, "text": "我才要说怎么又是你" # 树状格式,比较清晰,显示中文 }
反序列化
import json res_text = {"name": "\u5f20\u4e09", "password": "123456", "male": true, "money": null} # JSON文本格式的响应信息 res_dict = json.loads(res_text) # 转化为字典 print(res_dict['name']) # 方便获取其中的参数值
输出:张三
文件的序列化与反序列化
import json res_dict = {'name': '张三', 'password': '123456', "male": True, "money": None} # 字典格式 f = open("demo1.json","w") json.dump(res_dict, f)
查看同级目录,增长了一个demo1.json文件,内容为:
{"name": "\u5f20\u4e09", "password": "123456", "male": true, "money": null}
在项目中(和下面脚本文件同一路径下)新建demo2.json
文件,内容以下,保存
{ "name": "张三", "password": "123456", "male": true, "money": null }
新建Python文件
import json f = open("demo.JSON","r", encoding="utf-8") # 文件中有中文须要指定编码 f_dict = json.load(f) # 反序列化将文件句柄转化为字典 print(f['name']) # 读取其中参数 f.close()
何时使用JSON对象(字典)何时使用JSON文本?
通常在组装data参数时,建议使用字典格式,发送请求时用json.dumps(data)
转化为文本发送,收到请求后使用json.loads(res.text)
转化为字典,方便咱们获取其中的参数信息
练习:
注: method支持get和post,若是没有method,有data默认发post请求,没有data默认发get请求,type支持:form或json,没有默认发form格式
demo1.json
{ "url": "http://www.tuling123.com/openapi/api", "method": "get", "params": { "key": "ec961279f453459b9248f0aeb6600bbe", "info": "你好" } }
demo2.json
{ "url": "http://openapi.tuling123.com/openapi/api/v2", "method": "post", "type": "json", "data": { "reqType": 0, "perception": { "inputText": { "text": "附近的酒店" }, "inputImage": { "url": "imageUrl" }, "selfInfo": { "location": { "city": "北京", "province": "北京", "street": "信息路" } } }, "userInfo": { "apiKey": "ec961279f453459b9248f0aeb6600bbe", "userId": "206379" } } }
auth=(user,password)
req.encoding='utf-8'
来解决一部分中文乱码问题req.cookies.get(key)
来获取响应cookies中某个key对应的值import requests res = requests.get("https://www.baidu.com") print(res.status_code, res.reason) # 200 OK print(res.text) # 文本格式,有乱码 print(res.content) # 二进制格式 print(res.encoding) # 查看解码格式 ISO-8859-1 print(res.apparent_encoding) # utf-8 res.encoding='utf-8' # 手动设置解码格式为utf-8 print(res.text) # 乱码问题被解决 print(res.cookies.items()) # cookies中的全部的项 [('BDORZ', '27315')] print(res.cookies.get("BDORZ")) # 获取cookies中BDORZ所对应的值 27315
例如:
直接访问: https://demo.fastadmin.net/admin/dashboard?ref=addtabs
页面(页面能够看作一个返回html代码的GET请求)会提示请登陆后操做
登陆页面:https://demo.fastadmin.net/admin/index/login.html 用户名/密码:admin/123456(POST表单请求)
import requests s = requests.session() # 新建一个会话 s.post(url="https://demo.fastadmin.net/admin/index/login.html",data={"username":"admin","password":"123456"}) # 发送登陆请求 res = s.get("https://demo.fastadmin.net/admin/dashboard?ref=addtabs") # 使用同一个会话发送get请求,能够保持登陆状态 print(res.text)
若是不使用session()而单独发一个post登陆请求一个get请求是否能够呢?你能够本身试一下(requests.get()或post()每次都会创建一个新会话)
import requests url = "https://demo.fastadmin.net/admin/dashboard?ref=addtabs" cookies = {"PHPSESSID":"9bf6b19ddb09938cf73d55a094b36726"} res = requests.get(url=url, cookies=cookies) # 携带cookies发送请求 print(res.text)
两种方式的对比
token与session的区别
import requests import json app_key = 'kPoFYw85FXsnojsy5bB9hu6x' secret_key = 'l7SuGBkDQHkjiTPU3m6NaNddD6SCvDMC' img_url = '//upload-images.jianshu.io/upload_images/7575721-40c847532432e852.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240' # 获取token get_token_url = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={}&client_secret={}'.format(app_key,secret_key) token = requests.get(url=get_token_url).json().get("access_token") # 从获取token接口的响应中取得token值 # 识别图片文字 orc_url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token={}'.format(token) data = {"url": img_url} res = requests.post(url=orc_url, data=data) print(json.dumps(res.json(), indent=2, ensure_ascii=False)) # 格式化输出
显示结果:
{ "log_id": 4745549456768330559, "words_result_num": 6, "words_result": [ { "words": "我又问:那么什么时候,你带我回去?" }, { "words": "莲师言:你是你,我是我。你若不肯流连凡尘,自会回去。" }, { "words": "我问莲师:我从哪里来,要到哪里去?" }, { "words": "莲师言:世间种种变相,皆有起源。来与去皆是命中定数,不可参度。" }, { "words": "我再问:我是否还会再见到你?" }, { "words": "莲师言:你若心中有我,天然会再见。" } ] }
练习:
reqeusts支持Basic Auth(基本受权)和Digist Auth(摘要受权)
Oauth1.0 Oauth2.0 参考: requests官方文档
import requests import json # 基本受权能够直接在请求方法中使用`auth = (user,password)` res = requests.get("https://api.github.com/user", auth=("hanzhichao", "hanzhichao123")) print(json.dumps(res.json(), indent=2, ensure_ascii=False)) # 格式化输出
不管是cookie/session仍是appid/token方式,只用来验证请求者身份而不验证参数,所以没法防止请求参数被抓包拦截后篡改(仍携带合法的cookie或token)
数字签名(sign或sig)是用来对原始参数总体进行加密后生成的一个字符串,请求时参数和签名一期发送,服务器收到请求后对参数再次计算签名核对和所携带的签名是否一致。
例如: 原始签名{}
此为北京龙腾育才 Python高级自动化(接口测试部分)授课笔记
课程介绍
想要参加现场(北京)/网络课程的能够联系做者微信:lockingfree
- 高效学习,快速掌握Python自动化全部领域技能
- 同步快速解决各类问题
- 配套实战项目练习