「當 CI 上的測試案例跳紅燈時,新手 QA 會第一時間跑去修測試程式碼,中階 QA 會第一時間開 Bug 單給開發;而資深 SDET,會先用一套極度嚴密的診斷邏輯,在 3 分鐘內抓出犯罪現場的真兇。」
大家好,我是 Jane,一個每天在第一線處理跨平台(Web & App)自動化測試、跟 CI/CD Pipeline 與各種神秘失敗案例奮戰的自動化測試工程師(SDET)。
恭喜大家跟著我完成了第五部分關於 CI/CD 管道佈署與失敗報告診斷的討論!
從今天開始,我們邁入了整個系列文章的最終篇章:《第六部分:資深測試工程師真正需要處理的問題》。
在實務中,當 CI 跳出紅燈時,開發團隊最常發出的質疑就是:
如果每次 CI 跳紅燈,我們都沒辦法給出確鑿的證據,甚至把「測試程式碼寫爛導致的紅燈」當成 Bug 開給開發,久而久之,開發團隊就會對自動化測試產生嚴重的不信任感。
今天這篇文章,我們就來建立一套第一線 SDET 的標準排查邏輯與 7 步驟診斷樹,讓你精準切割責任,拿出讓開發團隊心服口服的排查結果!
當你看到 CI 上的 pytest 案例顯示 FAILED 時,請嚴格按照以下 7 個順序 進行邏輯排查:
┌─────────────────────────┐
│ 7 步驟排查決策樹 │
└────────────┬────────────┘
│
┌───────────────────────────┼───────────────────────────┐
▼ ▼ ▼
【第一階段:環境與重現】 【第二階段:日誌與資料】 【第三階段:責任歸屬判定】
1. 是否可人工手動重現? 4. 背景 API/Network 是 500? 6. 產品真實 Bug (Product)
2. 是否特定環境獨有? 5. 斷言值是否符合商業規格? 7. 測試腳本/環境 Bug (Test)
3. 測試資料是否一致/過期?
500 Internal Server Error 或 502 Bad Gateway > 產品後端/伺服器 Bug!(直接將 API Payload 與 Trace ID 附在 Bug 單上)。401 Unauthorized 或 403 Forbidden > 檢查是否為測試 Token 生成邏輯失效。TimeoutError: Element not visible 還是 AssertionError。TimeoutError,且畫面截圖顯示載入 Spinner 還在轉 > 檢查是否為 測試腳本缺乏條件式等待(Day 12),或是產品前端效能嚴重下滑。data-testid 或 Class。我們可以在 conftest.py 中利用 Hook,根據 Exception 類型自動為失敗案例加上初步的分類標籤,節省排查時間:
Python
# tests/conftest.py
import pytest
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
"""
pytest 鉤子:自動分析 Exception 類型,印出初步歸因建議
"""
outcome = yield
report = outcome.get_result()
if report.when == "call" and report.failed:
exc_info = call.excinfo
print(f"\n" + "="*50)
print(f"[SDET 診斷助手] 案例 {item.name} 執行失敗!")
# 判斷 1: 是否為 Playwright Timeout (通常為 DOM 變更或時序等待問題)
if exc_info.errisinstance(PlaywrightTimeoutError):
print("[初步歸因]: ⚠️ 疑似【測試腳本等待問題】或【DOM 定位器失效】")
print("[建議排查]: 請檢查畫面截圖,確認是否為動畫未完或 data-testid 變更。")
# 判斷 2: 是否為 pytest AssertionError (商業邏輯斷言失敗)
elif exc_info.errisinstance(AssertionError):
print("[初步歸因]: 🔥 疑似【產品真實 Bug】或【需求規格變更 (Spec Drift)】")
print("[建議排查]: 請對照預期值 (Expected) 與實際值 (Actual),確認商業邏輯。")
# 判斷 3: 其他 Exception (如 requests.exceptions.HTTPError)
else:
print(f"[初步歸因]: ⚡ 疑似【後端 API 異常】或【環境問題】: {exc_info.type.__name__}")
print("="*50)
當你排查完畢,確認是產品真實 Bug 時,開 Bug 單的品質決定了開發團隊對你的尊重程度。
「Jane: 結帳自動化測試爆掉了,CI 亮紅燈,你們 Dev 昨天的 Code 有 Bug,快去看一下!」
(Dev 打開一看,發現連哪裡壞了都沒寫,氣得說:這是你測試寫壞了吧!)
標題: [Bug][Staging][Checkout API] 購買數量為負數時 API 未正確攔截,回傳 500 錯誤
環境: Staging Pipeline Build #1082
排查過程:
- 手動於 Staging 環境重現,直接發送
POST /api/v1/checkout帶入quantity: -1。- 預期結果: API 應回傳
400 Bad Request與錯誤 JSON。- 實際結果: API 回傳
500 Internal Server Error,後端 Trace ID:tx_998123。- 附帶資源: 已附上 Playwright Trace 檔案與 API Request/Response Log。
建立了嚴密的失敗排查機制後,下一個資深 SDET 必須面對的長期戰役就是:「自動化測試技術債(Technical Debt)」。
為趕時程複製貼上的腳本、從不刪除的廢棄案例、只有原作者看得懂的黑盒子框架……這些技術債是怎麼形成的?
明天 Day 27,我們將深入探討:《 Day 27|自動化測試技術債如何形成?7 大常見的防禦性坑洞與解法 》。