共用方式為


將測試過程提前至單元測試階段

測試有助於確保程式碼按預期執行,但建置測試的時間和精力會佔用其他任務(例如功能開發)的時間。 有了這個成本,從測試中提取最大價值非常重要。 本文討論 DevOps 測試原則,重點關注單元測試的價值和左移測試策略。

過去,專門的測試人員編寫了大多數測試,許多產品開發人員並沒有學會編寫單元測試。 編寫測試可能看起來過於困難或讓人感覺工作量太大。 可能會有人懷疑單元測試策略是否能奏效,由於寫得不好的單元測試造成的不良體驗,或者擔心單元測試會取代功能測試。

描述有關採用單元測試的論點的圖形。

要實施 DevOps 測試策略,請務實並專注於建立動力。 雖然您可以堅持對新程式碼或可以乾淨重構的現有程式碼進行單元測試,但舊版程式碼庫允許一些相依性可能是有意義的。 如果產品程式碼的至關重要部分使用 SQL,則允許單元測試依賴於 SQL 資源提供者,而不是 模擬 該層,可能是短期推進的方法。

隨著 DevOps 組織的成熟,領導層更容易改進流程。 雖然變革可能存在一些阻力,但敏捷組織重視能夠明顯帶來回報的變革。 推銷更快的測試運行和更少的失敗的願景應該很容易,因為這意味著有更多的時間投入到通過功能開發創造新價值上。

DevOps 測試分類法

定義測試分類法是 DevOps 測試流程的一個重要面向。 DevOps 測試分類法會依依依性及其執行所需的時間對個別測試進行分類。 開發人員應該了解在不同場景中使用的正確測試類型,以及流程的不同部分需要哪些測試。 大多數組織將測試分為四個級別:

  • L0L1 測試是 單元測試,或依賴於被測程序集中的程式碼的測試,而不是其他任何測試。 L0 是一大類快速的記憶體內部單元測試。
  • L2 是可能需要組件及其他相依性(例如 SQL 或檔案系統)的 功能測試
  • L3 功能測試會在可測試的服務部署上執行。 此測試類別需要服務部署,但可能會使用 存根 來模擬關鍵服務的相依性。
  • L4 測試是針對生產環境執行的受限制整合 測試 類別。 L4 測試需要完整的產品部署。

雖然理想情況下,所有測試可隨時進行,但這不現實。 團隊可以選取 DevOps 程式中執行每個測試的位置,並使用 左移右移 策略,在程式中較早或稍後移動不同的測試類型。

例如,預期開發人員在提交之前一律會執行 L2 測試,如果 L3 測試執行失敗,提取要求會自動失敗,如果 L4 測試失敗,部署可能會遭到封鎖。 具體規則可能因組織而異,但強制執行組織內所有團隊的期望會使每個人都朝著相同的品質願景目標邁進。

單元測試指導方針

為 L0 和 L1 單元測試設定嚴格的指導方針。 這些測試需要非常快速和可靠。 例如,元件中每個 L0 測試的平均執行時間應該小於 60 毫秒。 組件中每個 L1 測試的平均執行時間應小於 400 毫秒。 此級別的任何測試都不應超過 2 秒。

一個 Microsoft 團隊在不到六分鐘的時間內並行運行了 60,000 多個單元測試。 他們的目標是將這個時間減少到不到一分鐘。 小組會使用下列圖表等工具追蹤單元測試執行時間,並針對超過允許時間的測試提交錯誤。

顯示持續關注測試執行時間的圖表。

功能測試指南

功能測試必須是獨立的。 L2 測試的關鍵概念是隔離。 適當隔離的測試可以以任何順序可靠地執行,因為它們可以完全控制它們所執行的環境。 在測試開始時必須知道狀態。 如果一個測試建立資料並將其保留在資料庫中,則可能會損毀依賴不同資料庫狀態的另一個測試的執行。

需要使用者身分的舊版測試可能已呼叫外部驗證提供者來取得身分。 這種做法帶來了一些挑戰。 外部相依性可能不可靠或是暫時無法使用,從而中斷測試。 這種做法也違反了測試隔離原則,因為測試可能會變更身分識別的狀態,例如權限,導致其他測試出現非預期的預設狀態。 考慮透過在測試框架內投資身分識別支援來防止這些問題。

DevOps 測試原則

若要協助將測試組合轉換至新式 DevOps 程式,請闡明品質願景。 團隊在定義和實施 DevOps 測試策略時應遵守以下測試原則。

顯示品質願景範例並列出測試原則的圖表。

左移以提前測試

測試可能需要很長時間才能執行。 隨著專案規模的擴大,測試數量和類型大幅成長。 當測試套件需要數小時或數天才能完成時,它們可能會延遲到最後一刻才執行。 測試的程式碼品質優勢要到程式碼提交很久之後才會實現。

長時間執行的測試也可能會產生耗時調查的失敗。 團隊可以建立對失敗的容忍度,尤其是在衝刺早期。 這種容忍度破壞了測試作為洞察代碼庫質量的價值。 長時間執行的最後一刻測試也增加了衝刺結束預期的不可預測性,因為必須支付未知數量的技術債務才能使程式碼可交付。

將測試左移的目標是透過在管道中較早執行測試任務,將品質移至上游。 透過測試和流程改進的結合,左移可以減少測試運行所需的時間,以及週期後期故障的影響。 左移可確保在變更合併至主要分支之前完成大部分測試。

顯示進行左移測試的圖表。

除了將某些測試責任前移以提高程式碼品質之外,團隊還可以將其他測試層面後移,或至 DevOps 週期的後期,以改進最終產品品質。 如需詳細資訊,請參閱 向右移動以在生產環境中進行測試

以最低可能的層級撰寫測試

編寫更多單元測試。 偏好具有最少外部相依性的測試,並專注於在建置過程中執行大部分的測試。 請考慮一個平行建置系統,只要元件和相關聯的測試卸除,就可以立即執行元件的單元測試。 在此層級測試服務的每個層面是不可行的,但原則是使用較輕的單元測試,如果它們可以產生與較重的功能測試相同的結果。

以測試可靠性為目標

不可靠的測試在組織上維護成本很高。 這樣的測試直接違背了工程效率目標,因為它很難自信地進行更改。 開發人員應該能夠在任何地方進行更改,並快速確信系統沒有遭到破壞。 保持高可靠性標準。 不鼓勵使用 UI 測試,因為它們往往不可靠。

撰寫可在任何地方執行的功能測試

測試可能會使用專門設計來啟用測試的專用整合點。 這種做法的原因之一是產品本身缺乏可測試性。 不幸的是,此類測試通常依賴於內部知識,並使用從功能測試角度來看並不重要的實現細節。 這些測試僅限於具有執行測試所需密碼和組態的環境,這通常不包括生產部署。 功能測試應該只使用產品的公用 API。

設計產品以提高可測試性

在成熟的 DevOps 流程中,組織可以全面了解在雲端節奏上交付優質產品的意義。 要大幅改變平衡,有利於單元測試而不是功能測試,需要團隊做出支援可測試性的設計和實作選擇。 對於什麼構成設計良好且實現良好的可測試性程式碼,有不同的想法,就像有不同的編碼風格一樣。 原則是,可測試性設計必須成為有關設計和程式碼品質的討論的主要部分。

將測試程式碼視為產品程式碼

明確說明測試代碼是產品代碼,可以清楚地表明測試代碼的質量對於運輸與產品代碼的質量一樣重要。 團隊應該以與對待產品代碼相同的方式對待測試代碼,並對測試和測試框架的設計和實施應用相同級別的謹慎。 這項工作類似於將組態和 基礎結構管理為程式碼。 為了完整,程式碼審查應考慮測試程式碼並將其保持在與產品程式碼相同的品質標準。

使用共用測試基礎結構

降低使用測試基礎設施產生可信品質訊號的門檻。 將測試視為整個團隊的共享服務。 將單元測試程式碼與產品程式碼一起儲存,並使用產品進行建置。 在建置程式中執行的測試也必須在開發工具下執行,例如 Azure DevOps。 如果測試可以在從本地開發到生產的每個環境中運行,那麼它們就具有與產品代碼相同的可靠性。

讓程式碼擁有者負責測試

測試代碼應該位於存放庫中的產品代碼旁邊。 若要在元件邊界測試程式碼,請將測試責任推送給撰寫元件程式碼的人員。 不要依賴其他人來測試組件。

案例研究:使用單元測試向左移動

Microsoft 小組決定以新式 DevOps 單元測試和左移流程的方式取代其舊版測試套件。 團隊追蹤每三週衝刺的進度,如下圖所示。 該圖涵蓋了第 78 到 120 次衝刺,這代表了 42 次衝刺在 126 週內完成,相當於大約兩年半的工作量。

該團隊在 Sprint 78 中從 27K 遺留測試開始,並在 S120 時已經完成零遺留測試。 一組 L0 和 L1 單元測試取代了大部分舊的功能測試。 新的 L2 測試取代了一些測試,許多舊的測試被刪除了。

顯示一段時間內測試投資組合餘額範例的圖表。

在需要兩年多時間才能完成的軟體之旅中,從流程本身中學到很多東西。 總體而言,在兩年內完全重做測試系統的努力是一項巨大的投資。 並非每個功能團隊都同時完成這項工作。 整個組織中的許多團隊在每個衝刺中都投入了時間,在某些衝刺中,這是團隊所做的大部分工作。 儘管很難衡量輪班的成本,但對於團隊的品質和績效目標來說,這是一個不容談判的要求。

入門指南

一開始,該團隊沒有干涉舊的功能測試,稱為 TRA 測試。 該團隊希望開發人員接受編寫單元測試的想法,特別是對於新功能。 重點是讓編寫 L0 和 L1 測試變得盡可能簡單。 團隊需要首先發展這種能力,並建立動力。

上圖顯示單元測試計數開始提早增加,因為小組看到了編撰單元測試的好處。 單元測試更容易維護、運行更快,並且失敗更少。 很容易獲得在提取請求流程中運行所有單元測試的支持。

直到 sprint 101 之前,該團隊才專注於編寫新的 L2 測試。 與此同時,TRA 測試數量從 Sprint 27,000 下降到 14,000 次,從 Sprint 78 下降到 Sprint 101。 新的單元測試取代了一些 TRA 測試,但根據團隊對其有用性的分析,許多測試被簡單地刪除了。

在衝刺 110 中,TRA 測試從 2100 躍升至 3800,因為在源樹中發現了更多測試並添加到圖表中。 事實證明,測試一直都在進行,但未能受到妥善的追蹤。 這不是一場危機,但重要的是要誠實並根據需要重新評估。

變得更快

一旦團隊獲得了極其快速和可靠的 持續整合 (CI) 訊號,它就成為值得信賴的產品品質指標。 下列螢幕擷取畫面顯示提取要求和 CI 管線的運作方式,以及經歷各個階段所需的時間。

顯示拉取請求和滾動 CI 管線運作的圖表。

從 pull request 到合併大約需要 30 分鐘,其中包括執行 60,000 個單元測試。 從代碼合併到 CI 構建大約需要 22 分鐘。 來自 CI 的第一個品質訊號 SelfTest 會在大約一小時後發出。 然後,大部分產品都會使用建議的變更進行測試。 在從 Merge 到 SelfHost 的兩小時內,產品會進行全面測試,變更已準備好進入生產。

使用指標

團隊會追蹤一張績效評量卡,如下範例所示。 在高層級上,計分卡會追蹤兩種類型的計量:健康情況或債務,以及速度。

顯示用於追蹤測試效能的計量計分卡的圖表。

對於即時站台健康情況指標,團隊會追蹤偵測時間、緩解時間,以及團隊攜帶的維修項目數量。 維修項目是團隊在即時網站回顧中確定的工作,以防止類似事件再次發生。 計分卡還跟踪團隊是否在合理的時間範圍內關閉維修項目。

針對工程健康指標,小組會追蹤每位開發者的活躍錯誤。 如果每個開發人員的小組有五個以上的錯誤,則小組必須在新功能開發之前優先修正這些錯誤。 該團隊還追蹤一些像安全這樣的特殊類別中的舊有錯誤。

工程速度指標衡量持續整合和持續交付 (CI/CD) 管道不同部分的速度。 總體目標是提高 DevOps 管道的速度:從一個想法開始,將程式碼投入生產,並從客戶那裡接收資料。

後續步驟