iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0

學習原因:

Parallel Testing 並行測試是同時執行多個測試案例的測試方法。這種方法的目的是在更短的時間內執行大量測試,從而加速測試過程並提高測試效率,是一個非常實用的技術。

學習目標:

  • 應用 pytest-xdist 套件進行並行測試
  • 了解進行並行測試時,需要注意 Test Case 的獨立性

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://ithelp.ithome.com.tw/upload/images/20231003/20162038cnsiANxnFa.png

圖片來源: https://twitter.com/agilecafe/status/1348241470353002499/photo/1

由於這種 Context Switching 消耗的資源對 Process 本身是沒有幫助的,都視為浪費,所以都不建議超過核心的數量。

執行並行測試時,需要注意測試案例之間的相互影響。因此,在進行並行測試時,必須仔細設計測試案例,確保它們之間的 獨立性

其中一個常見的例子,我們在測試很多時候需要登入帳號再進行操作。如果在並行測試中,同時登入相同的帳號,很容易會被互相影響而導致測試失敗。因此,我們會設計在不同的 Process 中,使用不同的帳號來執行測試。做法會是應用 pytest-xdistworker_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)

pytest-xdist 對 Fixture Scope 的影響

由於並行測試是在不同的 Process 下進行,Process 之間的資源並非共享的。
對於原來 Fixture Scope 的設定為 Session 時,原本 Fixture 應該在整個測試流程只會執行一次。
但使用並行測試後會變成每個 Process 都會執行一次,Scope 的影響範圍只會是同 Process 內的 Test Cases。

像是之前 Database 的連接寫成  Fixture,且 ScopeSession。當現在執行 4 個 worker 的並行測試,每個 Worker 都會自行連一次 Database,合共會有 4 次。

自動化測試 Test Case 的獨立性

  1. 減少依賴,隔離風險: 當一個 Test Case 失敗時,不會影響其他 Test Case 的執行,從而保證每個功能都能獨立地被測試,且降低了測試失敗的可能性。
  2. 可進行並行測試: 無須擔心與其他 Test Case 的衝突。
  3. 測試策略靈活: 獨立的 Test Case 可以在不同的情況下靈活使用,例如單獨運行,選擇性運行或按需運行。甚至執行順序不如預期也能順利執行。

只要有注意 Test Case 的獨立性,就可以簡單的應用 pytest-xdist 進行並行測試,以倍數的提升測試速度,所以非常重要。


從 0 到 1 建構測試框架與流程到這裡先告一段落了,建議如果已經從事軟體工作,可以嘗試用公司開發的系統練習寫測試,不管公司有沒有要推,也可以作為自己的 Side Project,累積實戰經驗。


上一篇
Day 27: Test Data 與 Environment Variable
下一篇
Day 29: 談談 Flaky Test
系列文
從 0 開始培育成為自動化測試工程師的學習指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言