在PC端登入公司的後臺管理系統或在手機上登入某個APP時,經常會發現登入成功後,返回引數中會包含token,它的值為一段較長的字串,而後續去請求的請求頭中都需要帶上這個token作為引數,否則就提示需要先登入。
這其實就是狀態或會話保持的第三種方式token
。
一. 什麼是token
token 由服務端產生,是客戶端用於請求的身份令牌。第一次登入成功時,服務端會生成一個包含使用者資訊的加密字串token,返回給客戶端並儲存在本地,後續客戶端只需要帶上token進行請求即可,無需帶上使用者名稱密碼。
token原理簡單概括如下:
-
使用者首次登入成功後,服務端會生成一個token值,服務端會將它儲存儲存在資料庫中,同時也會將它返回給客戶端;
-
客戶端拿到token值後,儲存在本地;
-
後續客戶端再次傳送除登入外的其他請求時,會把儲存在本地的token值作為引數一起傳送給服務端;
-
服務端收到客戶端的請求後,會拿傳送過來的token值與儲存在資料庫中的token值進行比較;
-
如果兩個token值相同, 則說明當前使用者處於登入狀態;
-
如果資料庫中沒有這個token值或者token值已經生效,則需使用者重新登入。
二. token場景處理
公司某管理後臺系統,登入後返回token,接著去請求其他介面時請求頭中都需要加上這個token,否則提示請先登入。
請求該系統的登入介面如下:
# @author: 給你一頁白紙
# 微信公眾號:測試上分之路
import requests
import json
headers = {"Content-Type": "application/json;charset=utf8"}
url = "http://127.0.0.1:5000/login"
_data = {
"username": "劉德華",
"password": "123456"
}
res = requests.post(url=url, headers=headers, json=_data).text
print(res)
結果如下:
{
"code": 1000,
"msg": "登入成功!",
"token": "sh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730dj"
}
在對扎樣的專案做介面自動化測試時,需要先請求登入介面拿到token,再去請求別的介面。每次請求其他介面時先請求一次登入介面,這樣做雖然可行,但這樣不僅會降低自動化的執行效率,而且每次都請求登入也會對伺服器資源造成浪費。
這裡介紹如下兩種處理思路。
1. 思路一
在執行用例之前,先請求登入介面,並將返回的token值儲存在檔案中(如yaml檔案),後續請求需要用到token值則從該檔案。
python中yaml檔案的讀寫請參考我之前的文章Python讀寫yaml檔案(使用PyYAML庫)。
1,執行介面自動化測試框架,初始化時先請求登入介面,獲取token值,並寫入指定的yaml檔案中。
# @author: 給你一頁白紙
# 微信公眾號:測試上分之路
import requests
import json
import yaml
def get_token():
'''
請求登入介面,獲取token
:return:
'''
headers = {"Content-Type": "application/json;charset=utf8"}
url = "http://127.0.0.1:5000/login"
_data = {
"username": "劉德華",
"password": "123456"
}
res = requests.post(url=url, headers=headers, json=_data).text
res = json.loads(res)
token = res["token"]
return token
def write_yaml(token):
'''
寫入yaml檔案
:return:
'''
t_data = {
"token": token
}
with open("yaml檔案路徑", "w", encoding="utf-8") as f:
yaml.dump(data=t_data, stream=f, allow_unicode=True)
if __name__ == '__main__':
token = get_token() # 獲取token
write_yaml(token) # 將token值寫入yaml檔案
2,執行測試用例時先讀取yaml檔案中token值,並將token加入headers中(也有些是將token放在請求引數中,視被測試專案具體情況而定),再傳送請求。
# @author: 給你一頁白紙
# 微信公眾號:測試上分之路
import requests
import yaml
import pytest
import json
def read_yaml():
'''
讀yaml檔案
:return:
'''
with open('yaml檔案路徑', 'r', encoding='utf-8') as f:
result = yaml.load(f.read(), Loader=yaml.FullLoader)
token = result["token"]
return token
def test_check_user():
'''
查詢個人資訊(需要先登入系統)
:return:
'''
# 先從yaml檔案中讀取token
token = read_yaml()
# 再將token新增到請求頭中
headers = {
"Content-Type": "application/json;charset=utf8",
"token": token
}
url = "http://127.0.0.1:5000/users/3"
res = requests.get(url=url, headers=headers).text
# 返回結果為json格式,轉換為字典
res = json.loads(res)
# 斷言code是否為1000
assert res["code"] == 1000
if __name__ == '__main__':
pytest.main()
這裡僅僅只是舉例說明,而在實際的框架中,我們需要把這些諸如yaml檔案的讀寫這樣的函式單獨封裝在某個模組中,供其他模組呼叫,這樣會程式碼會更加清晰簡潔。
2. 思路二
利用pytest中的Fixture函式,作用域設定為session,並返回token值,後續測試方法/函式呼叫該Fixture函式。
pytest中Fixture的使用請參考我之前的文章pytest(6)-Fixture(韌體)。
1,首先,在conftest中定義一個作用域為session的Fixture函式,用於請求登入介面返回token。
# @author: 給你一頁白紙
# 微信公眾號:測試上分之路
import pytest
import requests
import json
@pytest.fixture(scope="session")
def get_token_fixture():
'''
作用域為session的fixture函式,返回token
:return:
'''
headers = {"Content-Type": "application/json;charset=utf8"}
url = "http://127.0.0.1:5000/login"
_data = {
"username": "劉德華",
"password": "123456"
}
res = requests.post(url=url, headers=headers, json=_data).text
res = json.loads(res)
token = res["token"]
return token
2,接著,測試用例呼叫該Fixture。
def test_check_user(get_token_fixture):
'''
查詢個人資訊(需要先登入系統)
:return:
'''
# 通過Fixture函式g獲取et_token_fixture值,即token,再將token新增到請求頭中
headers = {
"Content-Type": "application/json;charset=utf8",
"token": get_token_fixture
}
url = "http://127.0.0.1:5000/users/3"
res = requests.get(url=url, headers=headers).text
res = json.loads(res)
print(res)
print(headers)
assert res["code"] == 1000
if __name__ == '__main__':
pytest.main()
執行測試用例結果如下:
說明思路二也是可行的,當然這裡只執行了一條測試用例,如果執行很多的用例,效果會是怎樣還沒去驗證,大家可以試試看。
三. 總結
- 相對於Session/Cookies來說,請求量較大或者涉及第三方介面的系統,使用token更適合。
- 有些專案token是放在請求頭中傳送的,而有一些專案則是放在請求引數裡傳送的,做介面自動化時要明確是哪種方式。
- 介面自動化處理token時這兩種思路可任選一種,如果使用pytest框架的話建議嘗試思路二。