Flaky Test 為不穩定測試,指的是同一個測試案例在不同的執行中可能會產生不同的結果,有時通過,有時失敗。這會大幅降低測試的可靠性。因此解決 Flaky Test 是自動化測試中的一個重要課題,需要針對不同的問題作出審查,以及優化。
monkeypatch
、 unittest.mock
和 pytest-rerunfailures
等套件。Flaky Test 可能是由於以下因素導致的:
而解決 Flaky Test 的方法可能包括:
隔離測試環境: 測試環境的變化可能導致測試結果不穩定。確保你在測試運行時使用一個穩定且一致的測試環境,避免外部干擾。例如應用 Docker 建一個獨立環境作測試。
避免競爭條件: 確保在測試案例中使用適當的資源分配,避免競爭條件的產生。如應用不同的 Test Data。
隔離外部依賴: 如果測試案例涉及外部服務、資料庫等依賴,考慮使用模擬服務或偽造物件來隔離這些依賴,以確保測試的穩定性。
monkeypatch
是pytest
內建的一個 fixture,用於模擬和修改運行環境。它允許你在測試中修改 Python 程序的內部操作,例如修改函數的行為、設定環境變數、模擬外部依賴等。
以下例子是模擬 api response,通常應用在需要第三方串接的 API 來作測試時,避免外部的依賴,會寫一個 Mock Service 來取代。也可以是用模擬實際情況下難以重現的情況,例如服務器錯誤、網絡中斷等。import requests import pytest from unittest.mock import Mock def get_data_from_service(): response = requests.get("https://example.com/api/data") return response.json() def test_get_data_from_service(monkeypatch): # 創建模擬的回應 mock_response = Mock() mock_response.json.return_value = {"key": "result"} # 模擬 requests.get mock_get = Mock(return_value=mock_response) monkeypatch.setattr("requests.get", mock_get) # 執行測試 response = requests.get("https://example.com/api/data").json() # 斷言結果 assert response == {"key": "result"} # 使用 monkeypatch.undo() 還原修改 monkeypatch.undo()
避免時間相關問題: 測試中的時間相關行為可能導致不穩定的結果。如果測試需要模擬時間,可以使用測試框架提供的時間模擬工具。可應用 unittest.mock
套件的 patch
來模擬。
from unittest.mock import patch
import time
def test_my_function_with_mock_time():
# 模擬 time.time() 返回固定值
with patch("time.time", return_value=1234567890.0):
result = time.time()
assert result == 1234567890.0
測試數據管理: 使用固定的、可控的測試數據,確保測試案例的執行結果可重複且一致。
建立重跑機制: 讓失敗的 Test Case 自動重跑以確認產品自身是否存在問題。
可使用
pytest-rerunfailures
套件,使自動重跑 Failed 的 Test Case。安裝套件後,在執行時加入參數--reruns
決定最多的 Rerun 次數。pip install pytest-rerunfailures # 失敗的 Test Case 最多 Rerun 5 次,都失敗才算 Test Case Failed. pytest --rerun 5
Rerun 成功,Test Case 的狀態則會轉成 Passed。在 Allure Report 會看到 Status 為 Passed,但會多了一個炸彈圖案在 Test Case 以標示此為 Flaky Test,打開 History 可以看到每次的執行狀況,從而審查不穩定狀況發生的原因。
修復問題根本原因: 如果你能夠確定 Flaky Test 的根本原因,儘可能修復問題,而不僅僅是處理測試失敗。
Flaky Test 的成因眾多,都需要透過觀察,發現問題,再選用適當的策略去避免。以上只是提供常見問題的解決方法,剩下的交給你思考囉。