偶發 bug 怎麼抓:重現率、日誌、變數隔離
#偶發缺陷 #日誌判讀 #缺陷重現 #QA 實戰 #QA 思維
偶發 bug 怎麼抓:重現率、日誌、變數隔離 有一種 bug 比「不會動」更難搞——是「有時候不會動」。 你在測結帳流程,十次裡有三次訂單狀態卡在「處理中」,其他七次正常。你截圖、記步驟、回報給工程師,他試了五次,每次都過。於是他說:「我這邊沒重現。」你說:「我真的看到了。」雙方開始通靈。 偶發 bug 沒有固定的重現路徑,但不代表只能靠運氣。標重現率、讀日誌、逐步隔離變數,就能把說不清楚的感覺,變成工程師能動手的資訊。 先標重現率 第一步先別急著找原因,先誠實標記這個 bug 的重現頻率: 100% :每次照步驟都能觸發。必現的 bug 最好修,因為有確定的重現路徑。 5 到 10 次裡出現幾次(偶發) :有條件觸發,但你還沒找到那個條件。這類最消耗雙方時間。 難以重現 :幾十次操作才出現一次,甚至只有真實用戶碰到過。 這個標註是在告訴工程師「要花多少力氣去重現它」。沒有重現率資訊,工程師試一次沒中就傾向關掉;有了「5 次出現 2 次」的標記,他知道要多試幾輪。同時也問問自己:能不能把重現率從偶發推到必現?調查就往這個方向走。 從日誌找線索 偶發 bug 最容易被忽略的習慣是:出現的當下沒有同步抓日誌,等想到才去翻,時間戳對不上,線索全斷。 正確做法是,在反覆觸發這個流程時,一邊開著: 前端 Console :有沒有 Uncaught TypeError、網路錯誤、被靜默吞掉的 Promise rejection? Network 面板 :哪個 request 在 bug 出現時回傳 4xx / 5xx?還是 pending 很久才 timeout? 後端 Server Log :找對應的 request 有沒有拋例外、有沒有 DB timeout。 前後端日誌對齊的關鍵是 Request ID 加時間戳 。如果後端每個 request 都有 trace id,你在 Network 面板找到那個 500 的 request header 裡的 X Request ID,就能直接讓工程師在後端 log 裡搜出那筆完整的執行鏈。少了這條線,前端看到 500,後端不知道要找哪一筆。 變數隔離 偶發的本質是: 有一個你還沒控制住的變數 。它可能是帳號、資料狀態、網路條件、瀏覽器快取、時間點,甚至是前一個測試遺留的髒資料。 隔離的方法是逐一固定變數,每次只放開一個: 1. 同帳號 :換一個乾淨帳號,bug 還在嗎?如果不在,問題跟帳號狀態有關(訂閱方案、權限、歷史資料)。 2. 同資料 :清掉快取、登出重登,確保每次操作的起始狀態一致。 3. 同網路 :切換到有線或穩定 Wi Fi,排除網路抖動。偶發的請求 timeout 有時候就是這樣消失的。 4. 同時間點 :有些 bug 只在整點、跨日、Token 過期前後出現。固定時間點,看看有沒有規律。 5. 同環境 :staging 偶發但 prod 必現,或相反——兩邊的環境變數、資料庫版本、第三方設定有什麼差異? 每固定一個變數,你就往「必現」靠近一步。最理想的結果是找到一個最小的重現條件:「用 A 帳號、清快取後、在半點整執行,重現率 100%」。這句話遠比「有時候會壞」有用。 我遇過的兩隻 我印象最深的兩隻偶發 bug,一隻最後是 race condition,一隻是快取。 第一隻出在「開始計時」按鈕。按一次就開始,沒什麼問題;但只要兩下之間不到半秒,就會同時開出兩個 session。後果不只是畫面怪:完成後點數有時算兩次、有時一次都沒算,還有紀錄在寫入時互相打架,直接不見。它之所以偶發,是因為要兩個請求剛好擠進同一個空窗。查到的原因很單純:開始的 API 沒有互斥保護,也沒有冪等 key,同一個使用者可以同時建兩個 session。知道是時序問題,就能刻意製造它:半秒內連點兩次。驗修復也照這個做:連點兩次,確認只建出一個 session,第二次呼叫回傳的是同一個 session ID。 第二隻更難纏。使用者的紀錄列表裡,偶爾多出一筆他沒建過的紀錄。時間戳跟真正那筆一模一樣,類型卻不對,還是失敗狀態。去後端資料庫查,這筆根本不存在。後端沒有、前端卻看得到,矛頭就指向前端的本地快取:開始時先在本地預建一筆,結束時沒清乾淨。這隻只在 Android 出現,頻率很低,手上只有兩次發生紀錄,兩次都在跑滿兩小時的 session 之後。根因到現在還在追,但「前後端資料對不上」這條線,已經把排查範圍縮到前端那一層。 偶發的常見成因 把常見的偶發成因記起來,能幫你更快鎖定方向: 時序競態(Race Condition) :兩個非同步操作的執行順序不固定,誰先回來就決定結果。常見於多個 API 並發、WebSocket 與 HTTP 交錯的場景。 快取狀態 :上一次操作的結果沒有正確清除,下一次操作拿到舊資料。重現時試試強制清除快取再走一遍。 外部相依 :第三方 SDK、支付 API、推播服務——偶爾慢、偶爾掛。這種偶發不是你的 bug,但你的系統得能優雅處理它。 測試資料殘留 :上一個測試流程沒清乾淨,這次操作的資料起點不一樣,觸發了某個邊界條件。 環境差異 :本地 / staging / prod 的設定不一致,導致行為在某個環境才會偶發。 看到偶發 bug,可以對著這張清單快速掃一遍,猜最有可能的方向再去日誌裡驗證。