這次,我掌握了 pytest 中 fixture 的使用及 pytest 執行測試的載入順序
先說經驗總結
- pytest 會在測試函式呼叫時自動查詢具有相同名稱的 fixture,並將其注入到測試函式中。
- pytest 在執行測試時會先進行測試用例的收集,然後再執行測試。
實操:[造數函式] 和 [測試用例] 都需要呼叫登入介面獲取使用者 token,既然都需要呼叫登入介面,那會不會出現 token 失效的情況呢?
例如有一個訂單查詢介面 orderList,呼叫 orderList 需要傳入的引數為:token、orderType、submitState、page 和 limit,其中 submitState 的可選值是固定的 [None,1,2],orderType 的可選值是由介面 getOrderType 返回的,呼叫 getOrderType 需要傳入 token。在這種場景下設計用例就引發了一系列的思考。
首先我共有三個.py 檔案,test.py,conftest.py 和 case_data.py,內容大致如下:
在寫 case_data 時,先後共寫過兩個版本,我描述一下思考過程,當前為第一個版本。
# conftest.py
@pytest.fixture(scope="session")
def tf_stu_token():
base_url = Environment.HOST_LAPI + 'login'
data = {
'userphone': Environment.userphone_stu,
'password': CT.to_md5(Environment.password_stu),
'phonecode': 86,
'type': 1
}
resp = requests.post(url=base_url, data=data)
assert resp.status_code == 200
token = resp.json()["data"]["token"]
return token
# case_data.py V1
def getOrderType(tf_stu_token): # !問題就出在這裡,在非測試函式的地方引用fixture並不會生效,但當時不知道
url = Environment.HOST_LAPI + 'getOrderType'
data = {
'token':tf_stu_token,
}
resp = requests.post(url=url,data=data)
return resp.json()['data'] # 會返回[0,1,2,3,4]
def data_orderList():
total = []
orderType_list = getOrderType()
submitState_list = [None,1,2]
for i in range(5):
item = []
case = {}
case['OrderType'] = orderType_list[i % len(orderType_list)]
case['submitState'] = submitState_list[i % len(submitState_list)]
item.append(case)
expect = {}
expect['code'] = 2000
item.append(expect)
item.append('正常入參')
total.append(item)
# token為空
total.append([{'OrderType': 0,'submitState': None}, {'code': 4001}, 'token為空'])
return total
'''
這個total最終為包含6條測試資料的列表:
[
[{'OrderType': 0,'submitState': None}, {'code': 2000}, '正常入參'],
[{'OrderType': 1,'submitState': 1}, {'code': 2000}, '正常入參'],
[{'OrderType': 2,'submitState': 2}, {'code': 2000}, '正常入參'],
[{'OrderType': 3,'submitState': None}, {'code': 2000}, '正常入參'],
[{'OrderType': 4,'submitState': 1}, {'code': 2000}, '正常入參'],
[{'OrderType': 0,'submitState': None}, {'code': 4001}, 'token為空']
]
'''
# test.py
import pytest
import requests
import case_data as CD
@ pytest.mark.parametrize("case, expect, desc", CD.data_orderList())
def test_orderList(tf_stu_token, case, expect, desc):
url = Environment.HOST_LAPI + 'orderList'
data = {
'token': tf_stu_token,
'orderType':case['orderType'],
'submitState':case['submitState'],
'page': 1,
'limit': 20
}
resp = requests.post(url=url, data=data)
assert resp.json()['code'] == expect['code']
測試後發現,造數函式報錯,原因是呼叫 getOrderType 時缺少引數 tf_stu_token。當時就很納悶,我隱約記得 fixture 函式不需要顯式呼叫呀,不應該是執行的時候會自動載入麼。報錯資訊大致如下:
查閱後發現,pytest 會在測試函式中呼叫時自動查詢具有相同名稱的 fixture,並將其注入到測試函式中。非測試函式並不能使用 fixture。 也有資料說 fixture 可以被非測試函式呼叫,但幾經實踐後並沒有成功。
於是為了在 case_data.py 中獲取 token,我決定在 case_data.py 中再另行呼叫一遍登入介面。修改後的 case_data.py 如下:
# case_data.py V2
def get_stu_token(userphone, password):
base_url = Environment.HOST_LAPI + 'login'
data = {'userphone': userphone,
'password': CT.to_md5(password),
'phonecode': 86,
'type': 1
}
response = requests.post(url=base_url, data=data)
token = response.json()["data"]["token"]
return token
token_stu = get_stu_token(Environment.userphone_stu, Environment.password_stu)
def getOrderType(): # !問題就出在這裡,在非測試函式的地方引用fixture並不會生效,但當時不知道
url = Environment.HOST_LAPI + 'getOrderType'
data = {
'token':token_stu,
}
resp = requests.post(url=url,data=data)
return resp.json()['data'] # 會返回[0,1,2,3,4]
def data_orderList():
total = []
orderType_list = getOrderType()
submitState_list = [None,1,2]
for i in range(5):
item = []
case = {}
case['OrderType'] = orderType_list[i % len(orderType_list)]
case['submitState'] = submitState_list[i % len(submitState_list)]
item.append(case)
expect = {}
expect['code'] = 2000
item.append(expect)
item.append('正常入參')
total.append(item)
# token為空
total.append([{'OrderType': 0,'submitState': None}, {'code': 4001}, 'token為空'])
return total
執行後可以正常執行,但我當時心中又有一個疑問,我在造數指令碼里呼叫登入介面,會不會導致測試指令碼里的 token 失效?經過實踐後得到結論:在造數函式中呼叫登入介面並不會致使測試指令碼中的 token 失效,原因是pytest 在執行測試時會先進行測試用例的收集,然後再執行測試,放在當前情景中,如果有影響,也是測試用例中呼叫登入介面後會致使造數指令碼中的 token 失效,可造數介面已經提供完價值了,token 失不失效也沒有任何影響了。
文中提到的引數化用的是@pytest.mark.parametrize,可能由於編輯器問題,釋出後變成了@user5ize,所以我在 @ 後增加了一個空格
相關文章
- pytest(4)-測試用例執行順序
- 【pytest】fixture 與 setup, teardown 的優先順序
- Pytest測試框架(三):pytest fixture 用法框架
- pytest fixture 使用
- Pytest測試框架(一):pytest安裝及用例執行框架
- 自動化測試 —— Pytest fixture及conftest詳解
- Pytest 順序執行,依賴執行,引數化執行
- Pytest學習(四) - fixture的使用
- 【pytest官方文件】解讀fixtures - 11. fixture的執行順序,3要素詳解(長文預警)
- 【pytest系列】- fixture測試夾具詳解
- pytest 精通 fixture
- 7.pytest 強大的 fixture (中)
- python @pytest.fixture示例及用法Python
- pytest介面測試之fixture傳引數request
- pytest 能否執行 nose 寫的測試用例
- 使用 ATX+pytest+allure-pytest 進行 IOS 的 UI 自動化測試iOSUI
- pytest 的 fixture 作用域問題
- Pytest(1) - 執行引數的使用
- 『德不孤』Pytest框架 — 12、Pytest中Fixture裝飾器(二)框架
- 『德不孤』Pytest框架 — 11、Pytest中Fixture裝飾器(一)框架
- 『德不孤』Pytest框架 — 13、Pytest中Fixture裝飾器(三)框架
- Pytest學習(十三)- 重複執行之pytest-repeat的使用
- Pytest系列(30)- 使用 pytest-xdist 分散式外掛,如何保證 scope=session 的 fixture 在多程式執行情況下仍然能只執行一次分散式Session
- pytest(6)-Fixture(韌體)
- pytest多程式/多執行緒執行測試用例執行緒
- 8.pytest 強大的 fixture (下)
- 6.pytest 強大的 fixture (上)
- pytest(2)-pytest-html測試報告HTML測試報告
- 關於 pytest 外掛 pytest-rerunfailures 和 fixture 的相容性問題AI
- Pytest單元測試框架——Pytest+Allure+Jenkins的應用框架Jenkins
- pytest進階之fixture函式函式
- pytest 中,pytest.ini 檔案為什麼會對 fixture 產生影響
- pytest:通過scope控制fixture的作用範圍
- 自定義xunit測試用例的執行順序
- python測試框架-pytestPython框架
- Python測試框架pytest入門基礎Python框架
- 『德不孤』Pytest框架 — 9、Pytest測試報告框架測試報告
- pytest 框架多個 test.py 檔案怎麼控制其執行順序,除了預設的檔名 ascii 碼順序執行還有什麼外掛或者方法可以控制其執行順序麼框架ASCII