Parallel Testing 並行測試是同時執行多個測試案例的測試方法。這種方法的目的是在更短的時間內執行大量測試,從而加速測試過程並提高測試效率,是一個非常實用的技術。
pytest-xdist
套件進行並行測試在 PyTest 中可以簡單使用 pytest-xdist
套件,便可執行並行測試。(可參考官方文件)
# 安裝 pytest-xdist
pip install pytest-xdist
# 執行 Parallel Testing 的時候,加入參數 -n <processes_number>,可以自行設定數量
pytest -n 2
# 也可以是設定為 auto,根據你的本機 CPU 核數量來決定,若 8 核則會啟動 8 個 worker process
pytest -n auto
pytest-xdist
是以 多核處理器 Multi-Processing 的方式執行並行測試,簡單解釋就是同時在不同的 CPU 核上執行測試,最理想的狀態一個核心同時只執行一個測試。
若超過核心的數量,等於就在同一個核心會有超過一個測試在執行,中間會出現 Context Switching
。就像是你同時做 2 個工作,中間需要不斷的切換,每次 2 個工作要進入狀態都需要花掉一些時間去回憶之前做到哪了。
圖片來源: https://twitter.com/agilecafe/status/1348241470353002499/photo/1
由於這種 Context Switching
消耗的資源對 Process 本身是沒有幫助的,都視為浪費,所以都不建議超過核心的數量。
執行並行測試時,需要注意測試案例之間的相互影響。因此,在進行並行測試時,必須仔細設計測試案例,確保它們之間的 獨立性。
其中一個常見的例子,我們在測試很多時候需要登入帳號再進行操作。如果在並行測試中,同時登入相同的帳號,很容易會被互相影響而導致測試失敗。因此,我們會設計在不同的 Process 中,使用不同的帳號來執行測試。做法會是應用 pytest-xdist
中 worker_id
Fixture,以 worker_id
作為參數傳入,會取得當前執行的 worker_id
。透過這個 worker_id
,則可以判斷使用哪個帳號來進行測試。
import logging
import pytest
@pytest.fixture
def login(worker_id):
# 當沒有執行並行時,worker_id 為 master,所以同時需要顧及沒用並行的情況
if worker_id == "gw0" or worker_id == "master":
email = "gw0@abc.com"
elif worker_id == "gw1":
email = "gw1@abc.com"
logging.info(f"worker {worker_id}: {email}")
return email
@pytest.mark.parametrize("num", [1, 2])
def test_parallel(num, login):
logging.info(f"{num}: Using {login} to login")
執行:
pytest -n 2
Output:
tests/test_parallel.py::test_parallel[2]
tests/test_parallel.py::test_parallel[1]
[gw1] PASSED tests/test_parallel.py::test_parallel[2]
[gw0] PASSED tests/test_parallel.py::test_parallel[1]
# 由於是並行測試,執行中不會顯示 log,因此會在 pytest.ini 開啟 log file 的設定
# 從 Report 中可以看到每個 test case 的 log
[INFO] worker gw0: gw0@abc.com (test_parallel.py:12)
[INFO] 1: Using gw0@abc.com to login (test_parallel.py:17)
[INFO] worker gw1: gw1@abc.com (test_parallel.py:12)
[INFO] 2: Using gw1@abc.com to login (test_parallel.py:17)
由於並行測試是在不同的 Process 下進行,Process 之間的資源並非共享的。
對於原來 Fixture Scope 的設定為 Session 時,原本 Fixture 應該在整個測試流程只會執行一次。
但使用並行測試後會變成每個 Process 都會執行一次,Scope 的影響範圍只會是同 Process 內的 Test Cases。
像是之前 Database 的連接寫成 Fixture
,且 Scope
為 Session
。當現在執行 4 個 worker 的並行測試,每個 Worker 都會自行連一次 Database,合共會有 4 次。
只要有注意 Test Case 的獨立性,就可以簡單的應用 pytest-xdist
進行並行測試,以倍數的提升測試速度,所以非常重要。
從 0 到 1 建構測試框架與流程到這裡先告一段落了,建議如果已經從事軟體工作,可以嘗試用公司開發的系統練習寫測試,不管公司有沒有要推,也可以作為自己的 Side Project,累積實戰經驗。