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對象的區別:
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 = 'http://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自動化全部領域技能
- 同步快速解決各類問題
- 配套實戰項目練習
原文出處:https://www.cnblogs.com/superhin/p/10338930.html