目錄
Python接口測試課程(第一天)-Python基礎(chǔ)
Python接口測試課程(第二天)-接口測試快速實踐
Python接口測試課程(第三天)-接口安全驗證,參數(shù)化及斷言
Python接口測試課程(第四天)-接口測試框架實現(xiàn)
更多學(xué)習(xí)資料請加添加作者微信:lockingfree獲取
第二天: Python接口測試(一)
簡單接口搭建(表單/REST)
五步教會你寫接口
首先要安裝flask包:
pip install flask
- 從flask中導(dǎo)入Flask類和request對象:
from flask import Flask, request
- 從當(dāng)前模塊實例化出一個Flask實例:
app=Flask(__name__)
- 編寫一個函數(shù)來處理請求
- 從請求對象中獲取數(shù)據(jù):
a=request.values.get("a");b=request.values.get("b")
- request.params: 字典格式,存儲請求中的url參數(shù)
- request.form: 字典格式,存儲請求中的表單數(shù)據(jù)
- request.values: 字典格式, 包含params和form中的值
- request.json: 字典格式, 存儲json類型的請求數(shù)據(jù), 如果請求類型非json, 值為空
- 進行業(yè)務(wù)處理:
sum = int(a) + int(b)
- 組裝并返回響應(yīng)數(shù)據(jù):
return str(sum) # http一般使用字符串傳輸數(shù)據(jù)
- 從請求對象中獲取數(shù)據(jù):
- 為接口指定接口地址和接受的方法:
@app.route("/add/", methods=["GET"]) # 寫到函數(shù)上面(裝飾器)
- 運行接口:
- 最后添加:
if __name__ == "__main__":
app.run()
2. 保存為```add.py```, 打開命令行,進入add.py所在目錄,運行```python add.py```?
完整代碼
# 1. 導(dǎo)入包
from flask import Flask, request
# 2. 實例化一個
app = Flask(__name__)
# 3. 編寫一個接口處理方法
@app.route("/add/", methods=["GET","POST"]) # 4. 掛載路由(指定接口的url路徑), 聲明接口接受的方法
def add():
# 3.1 從請求中獲取參數(shù)
# request.values {"a": "1", "b": "2"}
a = request.values.get("a")
b = request.values.get("b")
# 3.2 業(yè)務(wù)操作
sum = int(a) + int(b)
# 3.3 組裝響應(yīng)并返回
return str(sum)
# 5. 運行接口
if __name__ == '__main__':
app.run() # 默認5000端口,可以指定端口app.run(port=50001)
REST類型接口實現(xiàn)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/api/sub/", methods=["POST"])
def sub():
if not request.json: # 如果請求數(shù)據(jù)類型非json
return jsonify({"code": "100001", "msg": "請求類型錯誤", "data": None})
if not "a" in request.json or not "b" in request.json: # 如果參數(shù)中沒有a或者沒有b
return jsonify({"code": "100002", "msg": "參數(shù)缺失", "data": None})
a = request.json.get("a")
b = request.json.get("b")
result = str(float(a) - float(b)) # 使用float支持浮點數(shù)相減
return jsonify({"code": "100000", "msg": "成功", "data": result}) # 使用jsonify將字典數(shù)據(jù)轉(zhuǎn)換為json類型的相應(yīng)數(shù)據(jù)
if __name__ == '__main__':
app.run()
使用Postman測試接口(Form/Json)
編寫接口文檔
接口測試基礎(chǔ)
接口測試概念
接口測試是測試系統(tǒng)組件間接口的一種測試。
接口測試主要用于檢測外部系統(tǒng)與系統(tǒng)之 間以及內(nèi)部各個子系統(tǒng)之間的交互點。測試的重點是要檢查數(shù)據(jù)的交換,傳遞和控制管理過 程,以及系統(tǒng)間的相互邏輯依賴關(guān)系等。
接口測試目的
- 核心:保證系統(tǒng)的穩(wěn)定
- 手段:持續(xù)集成
- 目的:提高測試效率,提升用戶體驗,降低產(chǎn)品研發(fā)成本
接口測試一般流程
- 列出需求
- 安排資源,編寫接口用例 -> 用例評審
- 編寫接口測試代碼 -> 代碼評審codeReview
- 執(zhí)行接口測試
接口測試關(guān)注點
- 功能:功能實現(xiàn),實現(xiàn)與設(shè)計一致, 接口通過性測試
- 健壯性: 邊界值,容錯性
- 性能: 并發(fā)及壓測
- 穩(wěn)定性: 長期運行的穩(wěn)定性
- 安全性: SQL注入, session依賴, 數(shù)字簽名, http接口的安全性
常見接口種類
- Http/Https接口: 通過http/https協(xié)議傳送接口數(shù)據(jù)(通常按字符串/二進制傳輸), 如常見的網(wǎng)頁表單, https安全性更好
- RESTful Api: REST表述性狀態(tài)傳遞. 一種設(shè)計風(fēng)格,基于http/https協(xié)議, 把一切接口視為資源, 接口要分版本,在統(tǒng)一的域名下管理, 不同的方法(get/post..)做不同的事,通常請求及響應(yīng)使用json格式
- Web Service: SOAP簡單面向?qū)ο髤f(xié)議, 基于http實現(xiàn)的一種RPC方案.接口返回一些對象,可以直接通過操作對象,實現(xiàn)我們需要的業(yè)務(wù)處理.使用xml格式傳輸數(shù)據(jù)
- RPC接口: RPC為遠程方法調(diào)用, 有不同的實現(xiàn)方案,基于TCP/Http協(xié)議的都有. RPC可以想我們本地導(dǎo)入和調(diào)用對象一樣使用. Dubbo接口也是一種RPC接口.
常見接口數(shù)據(jù)類型
- 請求數(shù)據(jù)類型(Content-Type):
- application/x-www-form-urlencoded: 常規(guī)只有文本的網(wǎng)頁表單
- application/json: RESTful Api常用格式, 結(jié)構(gòu)清晰, 含有多層嵌套
- multipart/form-data: 既有文本,又有上傳文件或富文本框的混合數(shù)據(jù)表單
- text/xml: xml格式, RPC接口常用格式
- 響應(yīng)數(shù)據(jù)類型
- string/html: 返回字符串或網(wǎng)頁源碼
- json: RESTful Api常用響應(yīng)格式, 結(jié)構(gòu)清晰
- xml: RPC接口常用格式
常見接口安全驗證方式
- Auth_1.0/Auth_2.0: 通用接口授權(quán)方式
- Session依賴: 需要登錄之后才能進行接口操作
- Token驗證: 先要使用自己的appid/appsecret通過獲取token接口驗證身份獲取一個token(令牌,有一定有效期), 然后帶著token訪問接口
- 數(shù)字簽名: 將原本的參數(shù)按一定規(guī)則進行組合,配合時間戳或appsecret, 通過加密算法生成一個簽名sign, 攜帶簽名進行接口請求
常見接口請求方法
- GET: 獲取資源
- POST: 修改資源
- PUT: 上傳資源
- DELETE: 刪除資源
- HEAD: 只請求頁面首部
- PATCH: 補丁
- OPTIONS: 運行客戶端查看服務(wù)器性能
......
常見狀態(tài)碼(RESTful規(guī)范)
- 200系: 成功
- 200 OK - [GET]:獲取資源成功
- 201 CREATED - [POST/PUT/PATCH]:創(chuàng)建/修改成功
- 202 Accepted - [*]:任務(wù)接受
- 204 NO CONTENT - [DELETE]:刪除成功
- 300系: 重定向
- 301 Moved Permanently: 永久重定向
- 302 Found: 臨時重定向
- 400: 資源錯誤
- 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶請求錯誤
- 401 Unauthorized - [*]:沒有權(quán)限(鑒權(quán)失敗, 接口層)
- 403 Forbidden - [*] 資源禁止訪問(服務(wù)器層,沒有訪問權(quán)限)
- 404 NOT FOUND - [*]:資源不存在
- 405 Method Not Allowd: 訪問的方法不允許, 如用POST訪問只支持GET請求的接口
- 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)
- 410 Gone -[GET]:資源被永久刪除
- 422 Unprocesable entity - [POST/PUT/PATCH] 當(dāng)創(chuàng)建對象時,發(fā)生驗證錯誤
- 500系: 服務(wù)器內(nèi)部錯誤(接口崩潰或有Bug)
- 500 INTERNAL SERVER ERROR - [*]:服務(wù)器發(fā)生錯誤
接口業(yè)務(wù)類型
- 返回數(shù)據(jù)型接口: 只從數(shù)據(jù)庫讀取數(shù)據(jù)
- 業(yè)務(wù)操作型接口: 需要寫數(shù)據(jù)庫(接口測試需要要涉及參數(shù)化或環(huán)境清理)
快速上手接口測試
獲取接口文檔
- Wiki
- Word文檔
- Postman導(dǎo)出
- 抽象接口定義
- 接口管理平臺
接口文檔分析
- 功能分析: 是否能滿足業(yè)務(wù)(是否缺少某個前端需要的參數(shù)), 是否能滿足所有業(yè)務(wù)場景(是否有漏開發(fā)接口, 比如只開發(fā)了單品接口,沒開發(fā)套餐接口)
- 設(shè)計分析: 是否有不規(guī)范字段(如,nickname, passwd);不規(guī)范格式(如sex,用男,女而不是1,2);是否有易混淆字段(如amount和total);是否有單詞拼錯;是否有和數(shù)據(jù)庫字段對應(yīng)但名稱不一樣的(易錯)
- 接口分析: 協(xié)議類型(http要考慮安全);請求方法(是否規(guī)范);請求編碼格式(表單/Json/xml, 很多接口文檔不聲明,導(dǎo)致測試調(diào)試不通);接口授權(quán)方式;接口業(yè)務(wù)類型(關(guān)系到是否需要做參數(shù)化或環(huán)境清理); 返回值類型及結(jié)構(gòu)(關(guān)系到怎么斷言)
- 接口依賴: 需要什么環(huán)境準備和業(yè)務(wù)場景, 依賴那些接口, 有那些動態(tài)數(shù)據(jù), 預(yù)備環(huán)境怎么保障
- 參數(shù)分析: 各個參數(shù)的參數(shù)類型,組成規(guī)則,是否允許不傳,是否可以為空, 是否允許多傳參
- 業(yè)務(wù)分析: 如price字段必須和數(shù)據(jù)庫中的商品的price字段一致,才能校驗通過
- 非功能性: 接口的技術(shù)實現(xiàn)方案是否合理, 能否滿足高并發(fā)的性能要求, 邊界值/極限值的處理是否合適, 是否前后端都有數(shù)據(jù)格式校驗等(如精確度為秒級的訂單號生成器,在高并發(fā)下會導(dǎo)致生成同一訂單號的問題)
- 其他: 如反爬,對headers的一些限制和校驗, ip等限制
編寫接口用例
Excel/TestLink/禪道
- 單接口用例: 正常數(shù)據(jù)/邊界數(shù)據(jù)/異常數(shù)據(jù)(健壯性)/并發(fā)(一致性)/性能/安全性(抓包截取偽造/SQL注入/跨域請求)
- 場景用例: 列出常見的用戶場景, 用接口進行覆蓋, 業(yè)務(wù)場景壓測(尋找某個環(huán)節(jié)的性能瓶頸)
TestCase | Url | Method | DataType | a | b | Excepted | Actual | Status |
---|---|---|---|---|---|---|---|---|
test_add_normal | /api/add/ | GET | Url | 3 | 5 | 8 | ||
test_add_zero | /api/add/ | POST | FORM | 0 | 0 | 0 | ||
test_add_negetive | /api/add/ | POST | FORM | -3 | 5 | 2 | ||
test_add_float | /api/add/ | POST | FORM | 3.2 | 5.2 | 8.4 | ||
test_add_null | /api/add/ | POST | FORM | 0 |
執(zhí)行接口測試
- Postman: 功能調(diào)試
- Jmeter: 性能
接口自動化實踐
五步教會你寫接口自動化用例
需要安裝三方包:requests pytest pytest-html
pip install requests pytest pytest-html
- 導(dǎo)入requests模塊
import requests - 組裝請求參數(shù)和數(shù)據(jù)
url = 'http://127.0.0.1:5000/add/'
params = {"a":3, "b":5} # get請求url參數(shù), 字典格式
data = {"a":3, "b":5} # post請求請求數(shù)據(jù), 字典格式
- 發(fā)送請求得到response對象
resp = requests.get(url=url, params=params)
resp = requests.post(url=url,data=data)
- 解析response對象
- resp.text # 獲取響應(yīng)文本
- 斷言結(jié)果
assert resp.text == '8'
完整代碼:
# 1. 導(dǎo)入包
import requests
base_url = "http://127.0.0.1:5005"
# 2. 組裝請求
def test_add_normal():
# url 字符串格式
url = base_url + "/add/"
# data {} 字典格式
data = {"a": "1", "b": "2"}
# 3. 發(fā)送請求,獲取響應(yīng)對象
response = requests.post(url=url, data=data)
# 4. 解析響應(yīng)
# 5. 斷言結(jié)果
assert response.text == '3'
REST類接口自動測試方法
請求格式為json
三處不同:
- 必須通過headers指定內(nèi)容類型為application/json: ```headers={"Content-Type":"application/json"}
- 請求數(shù)據(jù)要轉(zhuǎn)化為字符串:
data=json.dumps(data)
(使用json.dumps需要import json) - json格式的響應(yīng)數(shù)據(jù),在接口調(diào)試通過和穩(wěn)定的情況下可以使用response.json()解析為字典格式,進行斷言
完整代碼:
# 1. 導(dǎo)入包
import requests
import json
base_url = "http://127.0.0.1:5005"
def test_sub_normal():
url = base_url + "/api/sub/"
headers = {"Content-Type": "application/json"} # 1. 必須通過headers指定請求內(nèi)容類型為json
data = {"a": "4", "b": "2"}
data = json.dumps(data) # 2. 序列化成字符串
response = requests.post(url=url, headers=headers, data=data)
# 3. 響應(yīng)解析 # 響應(yīng)格式為: {"code":"100000", "msg": "成功", "data": "2"}
resp_code = response.json().get("code")
resp_msg = response.json().get("msg")
resp_data = response.json().get("data")
# 斷言
assert response.status_code == 200
assert resp_code == "100000"
assert resp_msg == "成功"
assert resp_data == "2"
補充1: 感受Python黑科技之exec()動態(tài)生成用例:
數(shù)據(jù)文件: test_add_data.xls
TestCase | Url | Method | DataType | a | b | Excepted | Actual | Status |
---|---|---|---|---|---|---|---|---|
test_add_normal | /api/add/ | GET | Url | 3 | 5 | 8 | ||
test_add_zero | /api/add/ | POST | FORM | 0 | 0 | 0 | ||
test_add_negetive | /api/add/ | POST | FORM | -3 | 5 | 2 | ||
test_add_float | /api/add/ | POST | FORM | 3.2 | 5.2 | 8.4 | ||
test_add_null | /api/add/ | POST | FORM | 0 |
import requests
import xlrd
base_url = 'http://127.0.0.1:5005'
# 1.打開excel
wb = xlrd.open_workbook("test_add_data.xls")
# 2. 獲取sheet
sh = wb.sheet_by_index(0) # wb.sheet_by_name("Sheet1")
# 行數(shù) sh.nrows 列數(shù) sh.ncols
# 獲取單元格數(shù)據(jù)
# print(sh.cell(1,0).value)
# print(sh.nrows)
tpl = '''def {case_name}():
url = base_url + '/add/'
data = {{"a": "{a}", "b":"{b}"}}
response = requests.get(url=url, data=data)
assert response.text == '{expected}'
'''
for row in range(1, sh.nrows):
case_name = sh.cell(row,0).value
a = sh.cell(row, 4).value
b = sh.cell(row, 5).value
expected = sh.cell(row, 6).value
case = tpl.format(case_name=case_name, a=a, b=b, expected=expected)
exec(case)
動態(tài)生成的用例支持pytest發(fā)現(xiàn)和執(zhí)行
自動化接口用例運行
- 將自動化測試用例保存為test*.py,一個文件里可以寫多個用例, 如上面兩個接口保存為test_user.py
- 在自動化用例腳本所在目錄打開命令行, 運行
pytest
(運行所有test開頭的.py用例)或pytest test_user.py
(只運行該腳本中用例) - pytest一些參數(shù)
- -q: 安靜模式(不顯示環(huán)境信息)
pytest -q test_user.py
- --html=report.html:執(zhí)行完生成report.html報告(文件名可以自己指定)
pytest test_user.py --html=test_user_report.html
- --resultlog=test.log: 執(zhí)行完成生成執(zhí)行結(jié)果log文件
pytest test_user.py --resultlog=run.log
- -q: 安靜模式(不顯示環(huán)境信息)
requests庫詳解
請求方法
- requests.get()
- requests.post()
- requests.delete()
- .....
- requests.session() # 用來保持session會話,如登錄狀態(tài)
請求參數(shù)
- url: 接口地址, str
url="http://127.0.0.1:5000/add/"
- headers: 請求頭, dict
headers={"Content-Type": "application/json"}
- params: url參數(shù), dict
params={"a":"1":"b":"2"}
- data: 請求數(shù)據(jù), dict
data={"a":"1":"b":"2"}
- files: 文件句柄, dict
files={"file": open("1.jpg")}
- timeout: 超時時間,單位s, str, 超過時間會報超時錯誤```requests.get(url=url,params=params,timeout=10)
響應(yīng)解析
- resp: 響應(yīng)對象
- resp.status_code: 響應(yīng)狀態(tài)碼
- resp.text # 響應(yīng)文本
- resp.json() # 響應(yīng)轉(zhuǎn)化為json對象(字典)-慎用:如果接口出錯或返回格式不是json格式,使用這個方法會報錯
- resp.content # 響應(yīng)內(nèi)容, 二進制類型