不穩定的測試

「不穩定的」測試是指表現出間歇性或偶發性失敗的測試,其行為似乎具有非確定性。 有時它通過,有時它失敗,但原因尚不清楚。 本頁討論 pytest 功能,這些功能可以幫助以及其他用於識別、修復或減輕這些問題的通用策略。

為什麼不穩定的測試是一個問題

當使用持續整合 (CI) 伺服器時,不穩定的測試尤其麻煩,因為所有測試都必須通過才能合併新的程式碼變更。 如果測試結果不是一個可靠的信號——測試失敗意味著程式碼變更破壞了測試——開發人員可能會對測試結果產生不信任,這可能導致忽略真正的失敗。 這也是浪費時間的根源,因為開發人員必須重新運行測試套件並調查虛假的失敗。

潛在的根本原因

系統狀態

廣義上講,不穩定的測試表明測試依賴於某些未被適當控制的系統狀態——測試環境沒有被充分隔離。 較高層次的測試更可能是不穩定的,因為它們依賴於更多的狀態。

當測試套件並行運行時(例如使用 pytest-xdist),有時會出現不穩定的測試。 這可能表明測試依賴於測試順序。

  • 也許是另一個測試未能自行清理並留下數據,從而導致不穩定的測試失敗。

  • 不穩定的測試依賴於先前測試中的數據,而該測試本身沒有清理,並且在並行運行中,先前的測試並不總是存在

  • 修改全局狀態的測試通常不能並行運行。

過於嚴格的斷言

過於嚴格的斷言可能會導致浮點比較以及計時問題。 pytest.approx() 在這裡很有用。

線程安全

pytest 是單線程的,始終在同一個線程中順序執行其測試,從不自行產生任何線程。

即使在使用並行運行測試的插件的情況下,例如 pytest-xdist,通常也是通過產生多個進程並分批運行測試來工作的,而無需使用多個線程。

當然,測試和 fixtures 自己產生線程作為其測試工作流程的一部分是可能的(並且很常見)(例如,在後台啟動伺服器線程的 fixture,或執行產生線程的生產程式碼的測試),但必須小心

  • 確保最終等待任何產生的線程——例如在測試結束時,或在 fixture 的拆卸過程中。

  • 避免從多個線程使用 pytest 提供的原語 (pytest.warns(), pytest.raises() 等),因為它們不是線程安全的。

如果您的測試套件使用線程並且您看到不穩定的測試結果,請不要排除測試隱式使用 pytest 本身中的全局狀態的可能性。

其他通用策略

拆分測試套件

將單個測試套件拆分為兩個(例如單元測試與整合測試)是很常見的,並且僅將單元測試套件用作 CI 閘門。 這也有助於保持構建時間可管理,因為高層次測試往往較慢。 但是,這意味著可能會合併破壞構建的程式碼,因此需要額外警惕以監控整合測試結果。

失敗時的影片/螢幕截圖

對於 UI 測試,這些對於了解測試失敗時 UI 的狀態非常重要。 pytest-splinter 可以與 pytest-bdd 等插件一起使用,並且可以 在測試失敗時保存螢幕截圖,這有助於隔離原因。

刪除或重寫測試

如果該功能已在其他測試中涵蓋,則可以刪除該測試。 如果沒有,也許可以在較低層次重寫它,這將消除不穩定性或使其來源更加明顯。

隔離

Mark Lapierre 在 2018 年的一篇文章中討論了 隔離測試的優缺點

失敗時重新運行的 CI 工具

Azure Pipelines(Azure 雲 CI/CD 工具,前身為 Visual Studio Team Services 或 VSTS)具有一項功能,可以 識別不穩定的測試 並重新運行失敗的測試。

研究

這是一個有限的列表,請提交 issue 或 pull request 來擴展它!

  • Gao, Zebao, Yalan Liang, Myra B. Cohen, Atif M. Memon, 和 Zhen Wang. “使系統用戶交互測試可重複:我們應該在何時以及控制什麼?。” 收錄於 Software Engineering (ICSE), 2015 IEEE/ACM 37th IEEE International Conference on, vol. 1, pp. 55-65. IEEE, 2015. PDF

  • Palomba, Fabio, 和 Andy Zaidman. “重構測試異味是否會導致修復不穩定的測試?。” 收錄於 Software Maintenance and Evolution (ICSME), 2017 IEEE International Conference on, pp. 1-12. IEEE, 2017. Google Drive 中的 PDF

  • Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung, 和 Darko Marinov. “DeFlaker:自動檢測不穩定的測試。” 收錄於 2018 International Conference on Software Engineering 會議記錄. 2018. PDF

  • Dutta, Saikat 和 Shi, August 和 Choudhary, Rutvik 和 Zhang, Zhekun 和 Jain, Aryaman 和 Misailovic, Sasa. “檢測概率和機器學習應用程序中的不穩定測試。” 收錄於 第 29 屆 ACM SIGSOFT 國際軟體測試與分析研討會 (ISSTA) 會議記錄, pp. 211-224. ACM, 2020. PDF

  • Habchi, Sarra 和 Haben, Guillaume 和 Sohn, Jeongju 和 Franci, Adriano 和 Papadakis, Mike 和 Cordy, Maxime 和 Le Traon, Yves. “是什麼使這個測試變得不穩定?查明對測試不穩定性負責的類別。” 收錄於第 38 屆 IEEE 國際軟體維護與演進會議 (ICSME) 會議記錄, IEEE, 2022. PDF

  • Lamprou, Sokrates. “非確定性測試以及在哪裡可以找到它們:通過檢查測試順序依賴性,經驗性地調查不穩定測試和測試異味之間的關係。” 學士論文, Department of Computer and Information Science, Linköping University, 2022. LIU-IDA/LITH-EX-G–19/056–SE. PDF

  • Leinen, Fabian 和 Elsner, Daniel 和 Pretschner, Alexander 和 Stahlbauer, Andreas 和 Sailer, Michael 和 Jürgens, Elmar. “持續整合中不穩定測試的成本:工業案例研究。” Technical University of Munich 和 CQSE GmbH, Munich, Germany, 2023. PDF

資源