pytest參數化
1. Fixture參數之params參數可實現參數化
(參數可以為list和tuple,或者字典列表,字典元祖等)
1.1 參數化傳單個參數

1 # -*-coding: utf-8 -*- 2 import pytest 3 import requests 4 5 def userinfo(): 6 users = ['13630000009','18290000007','13040000004'] 7 return users 8 9 @pytest.fixture(params=userinfo()) 10 def login(request): 11 yield request.param 12 #刪除節點的操作,新增合作方、新增商場、新增出入口 13 14 @pytest.fixture(params=userinfo()) 15 def login1(request): 16 yield request.param 17 #刪除節點的操作,新增合作方、新增商場、新增出入口 18 19 def test_login(login,login1,): 20 url= "https://172.16.100.154/auth/getAccessTokenV2" 21 data = { 22 "username": login, 23 "passwd": 'a34fca232356ab316d3bb293b3f3d82d', 24 "randStr": None, 25 "ticket": None, 26 } 27 r = requests.post(url=url,json=data,verify=False) 28 print('登錄結果',r.text) 29 print('調用的測試數據:' + login)
此例中test_login方法被執行了三次,分別使用的數據為'13630000009','18290000007','13040000004',此結果類似於ddt數據驅動的功能。特別注意:這里的request參數名是固定的,然后request.param的param沒有s
可以把return request.param改成yield request.param,yield也是返回的意思,它和return的區別在於return返回后后面不能接代碼,但是yield返回后,后面還可以接代碼。
yield:方法調用夾具時,有刪除依賴時,記住先進后出原則,即放在最后面最先刪除
1.2 參數化傳多個參數

1 import pytest 2 import requests 3 4 # 測試賬號數據 5 test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"}, 6 {"user": "15310000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}] 7 8 @pytest.fixture(params=test_user_data) 9 def login(request): 10 user = request.param["user"] 11 passwd = request.param["passwd"] 12 print("\n") 13 print("登錄賬戶:%s" % user) 14 print("登錄密碼:%s" % passwd) 15 yield user,passwd 16 17 18 def test_login(login): 19 """登錄用例""" 20 url= "https://172.16.100.154/auth/getAccessTokenV2" 21 data = { 22 "username": login[0], 23 "passwd": login[1], 24 "randStr": None, 25 "ticket": None, 26 } 27 r = requests.post(url=url,json=data,verify=False) 28 print('登錄結果',r.text) 29 print("\n")
1.3 Fixture其他參數:
1.3.1.autouse參數:在夾具中設置autouse=True為自動調用執行,

1 import pytest 2 3 # @pytest.fixture(autouse=True) #設置為True讓autouse生效 4 # def setUp(): 5 # print('\nsetUp') 6 # yield 7 # print('\ntearDown') 8 # 9 # def testcase01(): 10 # print('1111111111') 11 # 12 # def testcase02(): 13 # print('2222222222') 14 15 # if __name__=='__main__': 16 # pytest.main(['-s', '-v', "test13.py"])\ 17 # 18 @pytest.fixture() #不設置autouse是默認autouse為false 19 def setUp(): 20 print('\nsetUp') 21 yield 22 print('\ntearDown') 23 24 def testcase01(setUp): 25 print('1111111111') 26 27 def testcase02(): 28 print('2222222222') 29 30 if __name__=='__main__': 31 pytest.main(['-s', '-v', "test13.py"])
1.3.2.ids參數:ids參數用於描述每個用例的運行場景

1 import pytest 2 import requests 3 4 5 # 測試賬號數據 6 test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"}, 7 {"user": "15300000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}] 8 9 @pytest.fixture(params=test_user_data,ids=[ 10 "輸入賬號1,密碼1,登錄成功", 11 "輸入賬號2,密碼2,登錄成功", 12 ]) 13 def login(request): 14 user = request.param["user"] 15 passwd = request.param["passwd"] 16 yield user,passwd 17 18 19 def test_login(login): 20 """登錄用例""" 21 url= "https://172.16.100.154/auth/getAccessTokenV2" 22 data = { 23 "username": login[0], 24 "passwd": login[1], 25 "randStr": None, 26 "ticket": None, 27 } 28 r = requests.post(url=url,json=data,verify=False)
運行結果
1.3.3. name參數:相對於把被fixture標記的方法重命名,主要是命名為中文,讓使用起來更易讀。如下圖所示案例:
注意點:設置了name即夾具的別名,就不能再使用函數名調用了,使用函數名調用會報錯
2. 使用@pytest.mark.parametrize()方法實現參數化
方法詳情:
parametrize(argnames,argvalues,indirect=False,ids=None,scope=None)
常用參數:
argnames:參數名
argnames:參數值(可以為list和tuple,或者字典列表,字典元組等),參數值有N個,用例就會執行N次。
3.1. 使用方式一

1 # -*-coding: utf-8 -*- 2 3 import pytest 4 import requests 5 6 # 測試賬號數據 7 test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"}, 8 {"user": "15300000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}] 9 10 @pytest.mark.parametrize("case_info",test_user_data) 11 def test_login(case_info): 12 print("\n") 13 print("用戶名",case_info['user']) 14 print("密碼",case_info['passwd']) 15 url= "https://172.16.100.154/auth/getAccessTokenV2" 16 data = { 17 "username": case_info['user'], 18 "passwd": case_info['passwd'], 19 "randStr": None, 20 "ticket": None, 21 } 22 r = requests.post(url=url,json=data,verify=False) 23 print('登錄結果',r.text)
3.2 使用方式二:類似於@unpack解包功能實現參數

1 # -*-coding: utf-8 -*- 2 import pytest 3 import requests 4 5 # 測試賬號數據 6 test_user_data = [('17530000005', 'b1b3e46675227369bd396eb44df1c900'), 7 ('15300000000', 'b1b3e46675227369bd396eb44df1c900')] 8 9 @pytest.mark.parametrize('user,passwd',test_user_data) 10 def test_login(user,passwd): 11 print("\n") 12 print("用戶名",user) 13 print("密碼",passwd) 14 url= "https://172.16.100.154/auth/getAccessTokenV2" 15 data = { 16 "username": user, 17 "passwd": passwd, 18 "randStr": None, 19 "ticket": None, 20 } 21 r = requests.post(url=url,json=data,verify=False) 22 print('登錄結果',r.text)
4. 數據驅動 Vs 關鍵字驅動
4.1 數據驅動自動化測試
在自動化測試框架中,從csv或excel或ymal讀取數據、輸出數據都在文件中執行,一個業務的實際返回值與業務的預期返回值都在數據文件中操作而不是在腳本里去執行校驗,這時候數據文件和腳本驅動為數據驅動框架。
優點和缺點
1)優點:
1.解耦合、測試數據預期結果與腳本分開
2.對於業務的改版或字段的增刪只需去修改腳本或者數據源
3.避免重復編寫腳本數據
2)缺點:
1.隨着業務量的增加、改版迭代次數快不方便維護
2.長時間可能會丟失數據
3.數據文件多、難以修改業務數據
4.2 關鍵字驅動
基於數據驅動之上建立的關鍵字驅動,從一個關鍵字的整合面對不同測試方法調用。從多個測試方法函數整合完成進階的關鍵字驅動,從數據和關鍵字的組合達到一個關鍵字驅動的效果。
關鍵字自動化測試驅動
在關鍵字驅動框架中,你可以創建一些函數或者一些測試方法。從函數庫中讀取關鍵字然后做相關調用。這種自動化驅動模型主要核心由數據驅動引擎、組件函數、支持庫和應用映射表組成。自動化測試首先由初始化腳本執行,這個腳本把高層測試表傳遞給高層驅動,高層驅動在處理這些表過程中,遇到中層驅動,中層處理也做中層處理。在底層處理時,嘗試底層測試同步 ,關鍵字驅動是對數據驅動做改善。
4.3 有哪幾種數據驅動方式
1.以硬編碼的方式寫在代碼里,簡單直觀,但代碼和數據未分離,不方便以后維護。
2.從文件讀取數據,如csv,excel、txt、xml等格式文件。不用修改測試邏輯,只需要維護測試數據。
excel表讀數據代碼示例

1 import pytest, xlrd, os, requests, json 2 3 # 獲取excel用例數據 4 def get_case_data(): 5 case_path = r"E:\scripts\newplatform\linshi\interface\yanshi\test_data.xlsx" 6 book = xlrd.open_workbook(case_path) 7 sheet = book.sheet_by_name('Sheet1') 8 case = [] 9 for i in range(0, sheet.nrows): 10 if sheet.row_values(i)[0] == 'mall用戶登錄': 11 case.append(sheet.row_values(i)) 12 return case 13 14 #注意點:excel中的json數據應為雙引號,否在json.loads時會報錯JsonEncodeError 15 16 class Test(): 17 18 # 調用獲取測試用例數據 19 case_data = get_case_data() 20 21 # 使用裝飾器參數化用例數據 22 @pytest.mark.parametrize('Function,TestCase,URL,Parameters', case_data) #注意此處填寫的參數應與表格一致,及表格多少列就將其參數名都寫出來,否則會報錯 23 def test_login1(self, Function, TestCase,URL, Parameters): 24 25 print(json.loads(Parameters)) 26 r = requests.post(url=URL,json=json.loads(Parameters),verify=False) 27 print(r.text) 28 assert r.text==r.text 29 30 if __name__ == "__main__": 31 pytest.main(["-s","-v","-w", "exceltest.py"])
3.直接調用接口獲取數據源。
4.本地封裝一些生成數據的方法。
Redis
4.4 數據驅動的優點
1. 像在循環里一樣,自動遍歷所有數據組合。
2. 某一組數據執行測試方法失敗,不會影響其他數據組合繼續執行。
3. 測試代碼不用加過多的數據判斷,要的只是對被測代碼的數據輸出和結果斷言。