Go Wiki:測試失敗
如果您注意到 Go 專案中的測試失敗,應該怎麼做?
測試目標
為 Go 包編寫(和執行)測試的目標是瞭解該包及其依賴項的行為。
Go 包的測試失敗可能會提供有關以下資訊:
- 包或其依賴項中的實現缺陷,
- 對包 API 的錯誤假設,
- 測試本身的錯誤(例如,有關時序的無效假設),
- 出乎意料的高資源需求(例如,記憶體或 CPU 時間),或
- 底層平臺中的錯誤或測試基礎設施中的缺陷(可能需要升級或規避)。
在某些情況下,測試失敗的原因可能不清楚:它可能由上述條件中的*一個以上*引起。 就像重複一項科學實驗一樣,讓測試多次失敗有時可以從特定的失敗模式中提供更多資訊。
但是,如果測試失敗但沒有提供任何新資訊,那麼該測試就沒有實現其目的。
查詢測試失敗
測試失敗通常從以下途徑注意到:
- Go 構建儀表板,尤其是在構建器分類期間;
- 待定更改上的 TryBot 或 SlowBot 失敗;
- 在特定包或包上執行
go test,無論是處理 Go 專案儲存庫中的工作,還是作為使用者自己模組中的 (例如)go test all的一部分; - 或在從原始碼安裝或測試貢獻的更改時執行
all.bash或all.bat。
對測試失敗進行分類
一旦注意到失敗,我們就需要對其進行*分類*。 分類的目標是確定:
- 失敗提供的資訊是新的嗎?
- 誰最適合分析來自失敗的新資訊?
識別新資訊
首先搜尋*開放式問題*,查詢失敗的關鍵詳細資訊,例如失敗測試的名稱和/或錯誤文字的其他獨特片段(例如,錯誤程式碼)。
如果您找到現有問題,請首先檢查問題討論,看看是否已修復該失敗,並且您的失敗資訊是否提供了相關的新資訊。 如果是這樣,請*在問題上發表評論*並附上詳細資訊:
- 描述您正在測試的 Go 版本 (
go version) - 如何以及在哪裡執行測試,例如:
go env輸出- 您的機器和作業系統配置
- 您的網路配置和狀態
- 您是否能夠重現失敗以及重現的頻率。
理想情況下,附加或連結到完整的測試日誌(可能放在 <details> 塊中)。
如果您找不到現有問題,請提交一個新問題。
提交問題
貼上足夠的測試日誌,以便將來的報告者能夠搜尋到該問題,包括測試的名稱及其日誌輸出中的任何獨特部分。(如果測試日誌很長 — 例如,如果它包含大型 goroutine 轉儲 — 考慮釋出較短的摘錄和/或將完整的失敗訊息包含在 <details> 塊中。)
您可以使用 fetchlogs 和 greplogs 工具來搜尋構建儀表板中類似的失敗。
# download recent logs
fetchlogs -n 1024 -repo all
# search logs for some regexp describing the failure message
greplogs -l -e $FAILURE_REGEXP
如果失敗似乎特定於某個包,請查閱 https://dev.golang.org/owners 查詢該包的維護者,並在問題中提及他們。(如果包未列出所有者,請檢查該包在 https://cs.opensource.google/go 上的近期歷史記錄,以及/或升級給能幫助識別相關所有者的人 — 並考慮使用您學到的知識更新所有者表!)
如果失敗似乎特定於 GOOS 或 GOARCH,請用相應的 GOOS 和/或 GOARCH 標籤標記問題,並在問題中提及 @golang/port-maintainers 的相關子團隊。
如果失敗似乎影響了至少一個*一流埠*,請將問題新增到當前釋出里程碑,並標記為 release-blocker。否則,將問題新增到 Backlog 里程碑。
如果失敗似乎特定於某個構建器(例如,網路連線問題或需要系統更新的平臺錯誤),請查閱 x/build/dashboard/builders.go 查詢該構建器的維護者,並在問題中提及他們。(對於沒有明確列出維護者的構建器,請提及 @golang/release 團隊。)
處理測試失敗
一旦為測試失敗提交了問題,相關的包、埠和/或構建器維護者應檢查從測試失敗中獲得的資訊,並透過以下一項或多項操作來決定如何*處理*它:
- 撤銷對被認為引入問題的程式碼或測試基礎設施的更改,
- 修復(或應用變通方法)失敗的根本原因,
- 收集更多資訊,透過訂閱問題更新和/或執行更多測試,
- 報告底層依賴項、平臺或測試基礎設施中的缺陷,以及/或
- 降低失敗的優先順序,透過在受影響的平臺上跳過失敗(或將這些平臺標記為已損壞),然後將問題移至未來的或
Backlog里程碑,以及/或刪除release-blocker標籤。
當維護者決定降低測試失敗的優先順序時,他們會確定*該測試的其他失敗將不會提供有用的新資訊*。 此時,測試不再履行其目的,維護者應抑制失敗 — 通常透過新增對 testenv.SkipFlaky 或 t.Skipf 的呼叫。
跳過測試失敗
當我們新增對 testenv.SkipFlaky 的呼叫時,我們的目標是消除不提供新資訊的失敗模式,同時儘可能保留測試的價值。
-
如果觀察到的失敗只是測試的幾種可能失敗模式之一,則僅為該失敗模式跳過測試。
- 例如,如果錯誤始終是特定的,如
syscall.ECONNRESET,請使用errors.Is檢查該特定錯誤。
- 例如,如果錯誤始終是特定的,如
-
如果認為失敗會影響特定
GOOS和/或GOARCH的所有版本,或者無法確定受影響的版本,請根據runtime.GOOS和/或runtime.GOARCH進行檢查,並僅跳過受影響的平臺。 -
如果失敗是由於*特定版本*的平臺上的錯誤,請根據
testenv.Builder或GO_BUILDER_NAME環境變數跳過測試。(如果測試對外部 Go 使用者失敗,他們可以選擇升級到不受影響的平臺版本 — 他們很可能應該看到測試失敗以瞭解該錯誤的存在!)- 還應考慮新增另一個環境變數,使用者和貢獻者可以設定該變數來確認錯誤並抑制失敗。
將構建器或埠標記為已損壞
平臺錯誤或核心包(如 os、net 或 runtime)中的錯誤可能會影響如此多的測試,以至於無法跳過失敗,或者可能會表現為編譯或連結時失敗。 如果發生此類錯誤,選項將更加有限:如果我們無法撤銷更改或修復或規避根本原因,並且不需要收集更多資訊,我們只能透過將*整個構建器或平臺*標記為已損壞來降低失敗的優先順序。
要將構建器標記為已損壞,請在其 x/build/dashboard/builders.go 配置中進行編輯,在 KnownIssue 欄位中新增一個問題;請注意,已知問題構建器通常會在儀表板分類期間被跳過。
一流埠的損壞構建器應將其已知問題標記為 release-blocker,等待決定是修復構建器還是放棄對受影響平臺版本的支援。
如果次要埠的所有構建器都已損壞,則該埠本身可能被視為已損壞。 討論 #53060 旨在解決如何處理已損壞的次要埠的問題。
此內容是 Go Wiki 的一部分。