您好,登錄后才能下訂單哦!
這篇文章給大家介紹使用pytest-xdist分布式插件如何保證scope=session 的fixture在多進程運行情況下仍然能只運行一次,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
使用 pytest-xdist 分布式插件可以加快運行,充分利用機器多核 CPU 的優勢
將常用功能放到 fixture,可以提高復用性和維護性
做接口自動化測試的時候,通常我們會將登錄接口放到 fixture 里面,并且 scope 會設置為 session,讓他全局只運行一次
但是當使用 pytest-xdist 的時候,scope=session 的 fixture 無法保證只運行一次,官方也通報了這一問題
pytest-xdist 的設計使每個工作進程將執行自己的測試集合并執行所有測試子集,這意味著在不同的測試過程中,要求高級范圍的 fixture(如:session)將會被多次執行,這超出了預期,在某些情況下可能是不希望的
盡管 pytest-xdist 沒有內置支持來確保 scope=session 的fixture 僅執行一次,但是可以通過使用鎖定文件進行進程間通信來實現
import jsonimport pytestfrom filelock import FileLock @pytest.fixture(scope="session")def session_data(tmp_path_factory, worker_id):if worker_id == "master":# not executing in with multiple workers, just produce the data and let# pytest's fixture caching do its jobreturn produce_expensive_data()# get the temp directory shared by all workersroot_tmp_dir = tmp_path_factory.getbasetemp().parent fn = root_tmp_dir / "data.json"with FileLock(str(fn) + ".lock"):if fn.is_file(): data = json.loads(fn.read_text())else: data = produce_expensive_data() fn.write_text(json.dumps(data))return data
若某個 scope = session 的 fixture 需要確保只運行一次的話,可以用上面的方法,直接套用,然后改需要改的部分即可(這個后面詳細講解)
官方原話:這項技術可能并非在每種情況下都適用,但對于許多情況下,它應該是一個起點,在這種情況下,對于 scope = session 的fixture 只執行一次很重要
xdist+fixture(文件夾) │ tmp(存放 allure 數據文件夾) │ conftest.py │ test_1.py │ test_2.py │ test_3.py │ __init__.py │
import osdef test_1(test):print("os 環境變量",os.environ['token'])print("test1 測試用例", test)
import osdef test_2(test):print("os 環境變量",os.environ['token'])print("test2 測試用例", test)
import osdef test_3(test):print("os 環境變量",os.environ['token'])print("test3 測試用例", test)
import osimport pytestfrom random import random @pytest.fixture(scope="session")def test(): token = str(random())print("fixture:請求登錄接口,獲取token", token) os.environ['token'] = tokenreturn token
pytest -n 3 --alluredir=tmp
scope=session 的 fixture 很明顯執行了三次,三個進程下的三個測試用例得到的數據不一樣,明顯不會是我們想要的結果
#!/usr/bin/env python# -*- coding: utf-8 -*-"""__title__ = __Time__ = 2021/4/27 11:28 __Author__ = 小菠蘿測試筆記 __Blog__ = https://www.cnblogs.com/poloyy/"""import jsonimport osimport pytestfrom random import randomfrom filelock import FileLock @pytest.fixture(scope="session")def test(tmp_path_factory, worker_id):# 如果是單機運行 則運行這里的代碼塊【不可刪除、修改】if worker_id == "master":"""【自定義代碼塊】 這里就寫你要本身應該要做的操作,比如:登錄請求、新增數據、清空數據庫歷史數據等等"""token = str(random())print("fixture:請求登錄接口,獲取token", token) os.environ['token'] = token# 如果測試用例有需要,可以返回對應的數據,比如 tokenreturn token# 如果是分布式運行# 獲取所有子節點共享的臨時目錄,無需修改【不可刪除、修改】root_tmp_dir = tmp_path_factory.getbasetemp().parent# 【不可刪除、修改】fn = root_tmp_dir / "data.json"# 【不可刪除、修改】with FileLock(str(fn) + ".lock"):# 【不可刪除、修改】if fn.is_file():# 緩存文件中讀取數據,像登錄操作的話就是 token 【不可刪除、修改】token = json.loads(fn.read_text())print(f"讀取緩存文件,token 是{token} ")else:"""【自定義代碼塊】 跟上面 if 的代碼塊一樣就行"""token = str(random())print("fixture:請求登錄接口,獲取token", token)# 【不可刪除、修改】 fn.write_text(json.dumps(token))print(f"首次執行,token 是{token} ")# 最好將后續需要保留的數據存在某個地方,比如這里是 os 的環境變量os.environ['token'] = tokenreturn token
pytest -n 3 --alluredir=tmp
可以看到 fixture 只執行了一次,不同進程下的測試用例共享一個數據 token
讀取緩存文件并不是每個測試用例都會讀,它是按照進程來讀取的
比如 -n 3 指定三個進程運行,那么有一個進程會執行一次 fixture(隨機),另外兩個進程會各讀一次緩存
假設每個進程有很多個用例,那也只是讀一次緩存文件,而不會讀多次緩存文件
所以最好要將從緩存文件讀出來的數據保存在特定的地方,比如上面代碼的 os.environ 可以將數據保存在環境變量中
還是上面栗子的代碼
pytest -n 2 --alluredir=tmp
可以看到 test_3 的測試用例就沒有讀緩存文件了,每個進程只會讀一次緩存文件,記住哦!
關于使用pytest-xdist分布式插件如何保證scope=session 的fixture在多進程運行情況下仍然能只運行一次就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。