Pytest系列(16)- 分散式測試外掛之pytest-xdist的詳細使用
阿新 • • 發佈:2020-11-25
一、前言
- 平常我們功能測試用例非常多時,比如有1千條用例,假設每個用例執行需要1分鐘,如果單個測試人員執行需要1000分鐘才能跑完
- 當專案非常緊急時,會需要協調多個測試資源來把任務分成兩部分,於是執行時間縮短一半,如果有10個小夥伴,那麼執行時間就會變成十分之一,大大節省了測試時間
- 為了節省專案測試時間,10個測試同時並行測試,這就是一種分散式場景
- 同樣道理,當我們自動化測試用例排常多的時候, 一條條按順序執行會非常慢,
pytest-xdist的出現就是為了讓自動化測試用例可以分散式執行,從而節省自動化測試時間
pytest-xdist是屬於程序級別的併發
二、分散式執行用例的設計原則(重中之重的重點)
- 用例之間是獨立的,用例之間沒有依賴關係,用例可以完全獨立執行
【獨立執行】
- 用例執行沒有順序,隨機順序都能正常執行
【隨機執行】
- 每個用例都能重複執行,執行結果不會影響其他用例
【不影響其他用例】
三、外掛安裝
pip3 install pytest-xdist -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
四、pytest-xdist通過一些獨特的測試執行模式擴充套件了pytest
測試執行並行化:
如果有多個CPU或主機,則可以將它們用於組合的測試執行。 這樣可以加快開發速度或使用遠端計算機的特殊資源。--looponfail:
跨平臺覆蓋:
您可以指定不同的Python解釋程式或不同的平臺,並在所有這些平臺上並行執行測試。
五、快速入門
這是執行程式碼的包結構
14xdist是專案資料夾名稱 │ conftest.py │ test_1.py │ __init__.py │ ├─test_51job │ │ conftest.py │ │ test_case1.py │ │ __init__.py │ ├─test_toutiao │ │ test_case2.py │ ├─test_weibo │ │ conftest.py │ │ test_case3.py │ │ __init__.py │
具體程式碼
5.1 最外層的conftest.py
import pytest
@pytest.fixture(scope="session")
def login():
print("====登入功能,返回賬號,token===")
name = "testyy"
token = "npoi213bn4"
yield name, token
print("====退出登入!!!====")
5.2 最外層的test_1.py
import pytest
@pytest.mark.parametrize("n", list(range(5)))
def test_get_info(login, n):
sleep(1)
name, token = login
print("***基礎用例:獲取使用者個人資訊***", n)
print(f"使用者名稱:{name}, token:{token}")
5.3 test_51job 包下的conftest.py
import pytest
@pytest.fixture(scope="module")
def open_51(login):
name, token = login
print(f"###使用者 {name} 開啟51job網站###")
5.4 test_51job 包下的test_case1.py
from time import sleep
import pytest
@pytest.mark.parametrize("n", list(range(5)))
def test_case2_01(open_51, n):
sleep(1)
print("51job,列出所有職位用例", n)
@pytest.mark.parametrize("n", list(range(5)))
def test_case2_02(open_51, n):
sleep(1)
print("51job,找出所有python崗位", n)
5.5 test_toutiao包下的test_case2.py
from time import sleep
import pytest
@pytest.mark.parametrize("n", list(range(5)))
def test_no_fixture(login, n):
sleep(1)
print("==沒有__init__測試用例,我進入頭條了==", login)
5.6 test_weibo包下的conftest.py
import pytest
@pytest.fixture(scope="function")
def open_weibo(login):
name, token = login
print(f"&&& 使用者 {name} 返回微博首頁 &&&")
5.7 test_weibo包下的 test_case3.py
from time import sleep
import pytest
@pytest.mark.parametrize("n", list(range(5)))
class TestWeibo:
def test_case1_01(self, open_weibo, n):
sleep(1)
print("檢視微博熱搜", n)
def test_case1_02(self, open_weibo, n):
sleep(1)
print("檢視微博范冰冰", n)
5.8 不使用分散式測試的命令和所需執行時間
pytest -s
可以看到,執行一條用例大概1s(因為每個用例都加了 sleep(1) ),一共30條用例,總共執行30s;那麼如果有1000條用例,執行時間就真的是1000s
5.9 使用分散式測試的命令和所需時間
pytest -s -n auto
知識點
- 可以看到,最終執行時間只需要6s,我的電腦是真6核,假12核
- -n auto:可以自動檢測到系統的CPU核數;從測試結果來看,檢測到的是邏輯處理器的數量,即假12核
- 使用auto等於利用了所有CPU來跑用例,此時CPU佔用率會特別高
5.10 可以指定需要多少個CPU來跑用例
pytest -s -n 2
5.11 pytest-xdist 是可以和 pytest-html 很好的相結合
pytest -s -n auto --html=report.html --self-contained-html
六、pytest-xdist 按照一定的順序執行
pytest-xdist預設是無序執行的,可以通過 `--dist` 引數來控制順序
--dist=loadscope
- 將按照同一個模組module下的函式和同一個測試類class下的方法來分組,然後將每個測試組發給可以執行的worker,
確保同一個組的測試用例在同一個程序中執行
- 目前無法自定義分組,按類class分組優先於按模組module分組
--dist=loadfile
按照同一個檔名來分組,然後將每個測試組發給可以執行的worker,確保同一個組的測試用例在同一個程序中執行
七、如何讓scope=session的fixture在test session中僅僅執行一次
pytest-xdist是讓每個worker程序執行屬於自己的測試用例集下的所有測試用例
這意味著在不同程序中,不同的測試用例可能會呼叫同一個scope範圍級別較高(例如session)的fixture,該fixture則會被執行多次,這不符合scope=session的預期
7.1 如何解決
雖然pytest-xdist沒有內建的支援來確保會話範圍的夾具僅執行一次,但是可以通過使用鎖定檔案進行程序間通訊來實現。
7.2 小例子
- 下面的示例只需要執行一次login(因為它是隻需要執行一次來定義配置選項,等等)
- 當第一次請求這個fixture時,則會利用FileLock僅產生一次fixture資料
- 當其他程序再次請求這個fixture時,則會從檔案中讀取資料
import pytest
from filelock import FileLock
@pytest.fixture(scope="session")
def login():
print("====登入功能,返回賬號,token===")
with FileLock("session.lock"):
name = "testyy"
token = "npoi213bn4"
# web ui自動化
# 宣告一個driver,再返回
# 介面自動化
# 發起一個登入請求,將token返回都可以這樣寫
yield name, token
print("====退出登入!!!====")