天天看點

谷歌測試定律

什麼是谷歌測試定律?

軟體測試(Software Testing)是軟體工程(Software Engineering)中不可或缺的一個過程。軟體測試觸發預定義的測試步驟、比較軟體的實際輸出結果和預期輸出結果,以此來評價軟體品質(Quality),判斷軟體的實作是否滿足設計目标和使用者需求。隻有經過嚴格測試的軟體,才能釋出給使用者使用。在實際中,根據 測試階段的不同,軟體測試可以分為:

  • 單元測試 : 測試對象通常是一個函數(Function)或一個類(Class)。單元測試與軟體代碼高度相關,通常由開發人員自己完成。
  • 元件測試 : 測試對象通常是一個子產品(Module),目的是驗證子產品的功能是否滿足設計目标。元件測試通常和軟體開發同步進行。
  • 內建測試 : 測試對象可以是一個獨立軟體實體(Entity)的對外接口(本質上測試的是這個軟體實體對外呈現的功能);也可以是多個相鄰軟體實體互相之間的接口(本質上測試的是多個相鄰軟體實體呈現的整體功能)。內建測試聚焦于軟體功能,一般在軟體開發部分或全部完成後進行。
  • 系統測試 : 測試對象是包含了所有軟體實體的真實系統。系統測試從使用者的角度設計測試步驟,目的是檢驗系統是否滿足使用者需求。一般在系統所有軟體都開發完成後進行。

在谷歌,測試的分類更多地強調 測試範圍,而不是測試階段。具體來說,谷歌把軟體測試分為:

  • Small Tests (小範圍測試): 通常對應單元測試群組件測試。
  • Medium Tests (中等範圍測試): 通常對應內建測試。在谷歌,Medium Tests強調的測試對象是互相之間有直接接口或 互操作 (Interoperation)關系的 相鄰 軟體子產品/軟體實體。
  • Large Tests (大範圍測試): 通常對應系統測試。

在長期的測試實踐中,谷歌發現,不同的測試範圍或階段中發現的軟體Bug(即缺陷、漏洞,下同),其解決成本(Fixing Cost)具有極其顯著的差别。舉例來說,解決一個小範圍測試(單元測試)中發現的軟體Bug需要花費的成本是5美金左右,解決一個中等範圍測試(內建測試)中發現的軟體Bug的成本在500美金左右,而解決一個大範圍測試(系統測試)中發現的軟體Bug的花費則高達5000美金。

谷歌的這一經驗資料在軟體行業中引起了廣泛共鳴、得到了許多人的認同。在這裡,筆者以更加科學的方式來描述谷歌的這一發現,并将其命名為 谷歌測試定律。

[ 谷歌測試定律]. 随着測試階段的推進(Small Tests -> Medium Tests -> Large Tests,或單元測試 -> 元件測試 -> 內建測試 -> 系統測試),測試中所發現的軟體Bug的解決成本呈 指數級增長。

為什麼谷歌測試定律成立?

軟體Bug一旦被發現,我們需要做的事情是确定的,那就是找到軟體Bug産生的原因、修改軟體代碼、然後驗證代碼的修改是否确實解決了Bug。是以:

Bug解決成本 = Bug定位成本 + 代碼修改成本 + 修改驗證成本
  • Bug定位成本 : 一旦發現Bug,首先需要回答的是, 引起Bug的原因是什麼?誰負責解決Bug? 不同的測試階段最大的差別就是 被測對象 (Tested Object)不同。被測對象既可以小到一個函數,也可以大到整個系統。從技術角度來說,被測對象的範圍越廣,可能引起Bug的嫌疑子產品就越多,精确地找到真正引起Bug的子產品就越困難;從組織角度來說,被測對象的範圍越廣,牽涉到的部門和個人就越多,針對Bug産生原因和Bug責任人的反複讨論和溝通所耗費的成本就越高。根據經驗,随着測試階段的推進,被測對象的範圍将成倍擴大,牽涉到的人員也将成倍增加,是以通常來說 Bug定位的成本也是成倍增加的 。
  • 代碼修改成本 : 一般來說,隻要精确地找到了産生Bug的軟體代碼,那麼解決Bug所帶來的代碼改動量是确定和一緻的。是以,不同的測試階段所發現的軟體Bug,其需要的代碼修改成本可以認為是相等的。
  • 修改驗證成本 : 軟體Bug的解決意味着軟體代碼的改動(Change)。一切代碼改動都需要被充分地驗證。我們需要確定: (1)代碼的改動确實解決了我們發現的Bug,(2)代碼的改動沒有破壞任何已有的功能。在執行層面,最基本的一個要求就是, 修改後的軟體包需要被拿到發現軟體Bug的測試環境中去驗證 。如果依然存在問題,那麼代碼修改無效,需要重新修改;隻有測試用例通過了,才能認為修改是有效的。一般來說,越往後期的測試階段,測試的環境越複雜,測試的執行時間越長,測試花費的人力成本越高。舉例來說,單元測試可能隻要數秒鐘就能完成并且一定是自動化的,而系統測試則可能需要消耗人力并要一天甚至幾天才能完成。是以,随着測試階段的推進, 軟體改動的驗證所花費的成本是成倍增長的 。

綜合Bug定位成本、代碼修改成本和修改驗證成本,我們發現,軟體Bug的解決成本确實是随着測試階段的推進成倍增加的。從數學角度看,總的趨勢就是指數級增長的。至于這個指數曲線的 底數的大小(決定指數曲線增長幅度),雖無法精确地給定,但可以确定的是, 當軟體項目越大型、軟體架構越複雜、參與人員越分散時,指數曲線的底數就越大,Bug解決成本的增長幅度就越快。

  • 測試資源要向前期測試階段傾斜 。為何要把有限的測試資源更多地投入到前期測試階段?筆者從可行性和必要性兩個方面給出回答。在讨論可行性之前,我們明确: [ 測試追溯定律 ]. 軟體測試的各個不同階段,凡是在目前測試階段發現的軟體Bug,一定可以在 前一個 測試階段或 更早的 測試階段,通過修改或者增加一個測試用例來重制。 在實際中,由于各種因素(測試覆寫度不夠高、測試力度不夠強、測試工具不夠可靠、測試樣本不夠可信等),軟體Bug可能會遺漏到後續的測試階段。但是從理論上說,每個測試階段都是有可能發現全部潛在軟體Bug的。通過加大前期測試的投入、優化前期測試的過程、提升前期測試的效果,來減少遺漏到後期測試階段的Bug數量,這條路是 可行 的。另外,根據谷歌測試定律,同一個軟體Bug,在後期測試階段被發現,相比在前期測試階段被發現,其解決成本可能要高一個數量級。為了節省公司成本、提高産品品質,我們應該盡可能地在前期測試階段發現更多的Bug。為此,我們務必要確定前期測試的有效性和覆寫度。前期測試階段的高度自動化,有助于實作這樣的目标。在總的測試資源有限的情況下,将更多的測試資源投入到前期測試階段是 必要 的。反過來說,如果前期階段的測試不充分,導緻大量本該在前期測試階段被發現的Bug遺漏到後期測試階段才被發現。到時候,我們可能需要投入巨量的人力物力去解決這些Bug。這對部門和公司來說,将是難以承受之重。
  • 測試工作要盡可能早地開展 。在 靈活 時代,測試無須等待軟體開發完成之後才展開,而是與軟體開發同步進行。具體來說,在每個疊代周期,軟體開發緻力于傳遞一個或多個可供使用者使用的功能點。這有助于測試工作的提早介入。測試開展得越早,軟體Bug發現得也就越早,解決軟體Bug的成本也就越低。在實際中,測試工作的開展不僅受制于軟體開發進度,還受制于測試自身所依賴的外部軟體和工具。通過使用模拟器技術(即 Mock ),我們可以減少對外部的依賴,不僅避免測試進度受制于人,而且将測試更多地聚焦在被測對象身上。
  • 千方百計縮短測試時間 。狹義的測試時間指測試步驟的執行時間,廣義的測試時間指從開發人員送出代碼到獲得測試回報結果的時間間隔。 縮短測試時間,不僅有利于提升軟體測試的生産力(機關時間執行更多的測試),而且有利于提升軟體開發的生産力 。很多時候,軟體開發是一個反複送出代碼的過程。如果測試的驗證速度很快,那麼代碼的送出就會更頻繁,軟體開發的效率也就得到了提高。任何一個測試階段,無論是單元測試還是系統測試,加快測試速度、縮短回報時間,都是很重要的。在實際中,通過改進系統的可測性、并行或分布式執行測試用例等,可以有效地提高測試速度、縮短測試時間。
  • CBRT: 基于代碼改動的回歸測試 。所謂CBRT(Change-Based Regression Testing),指的是每次代碼改動均執行回歸測試用例。在軟體開發中,代碼的改動(Change)是 常态 。新功能實作、Bug修複、代碼重構等都會帶來代碼的修改。回歸測試(Regression Testing)是確定代碼改動不破壞已有功能的重要舉措。然而,回歸測試能不能發揮更大的作用,與回歸測試的執行時間有關系。是代碼每次改動就執行回歸測試,還是許多改動合在一起後再執行回歸測試,有很大差别。前者,回歸測試一旦發現Bug,責任人是清楚的,解決Bug也更容易;而後者,回歸測試一旦發現Bug,單單排查原因、找到責任人就需要耗費大量的時間。是以, 代碼一旦發生改動就立即執行回歸測試是很有必要的 。在谷歌,考慮到每次代碼改動均執行所有回歸測試(測試集可能非常大)帶來的開銷較大。為此,基于對代碼子產品和測試用例的 關聯度分析 ,在谷歌,每次代碼改動隻執行 回歸測試子集 ,即隻執行那些可能受到被改動代碼影響的測試用例的集合。
  • 對測試遺漏出去的每一個Bug進行EDA 。無論前期測試做得如何好,我們都不能百分之百保證不會遺漏Bug到後期測試階段。也就是說,隻要後期測試階段發現了軟體Bug,那就意味着前提測試階段具有改進的空間。那麼,如何持續地改進前期測試呢? 筆者認為,針對每一個遺漏到後期測試階段的軟體Bug,至少有兩件事情是可以做的。首先,開發人員需要做代碼改動,而 前期測試人員也應該針對測試用例做改進 。根據測試追溯定律,後期測試發現的軟體Bug一定可以通過修改或增加一個前期測試用例來複現。這樣,我們可以基于改進後的前期測試用例對代碼改動進行驗證。另外, 前期測試人員需要進行EDA (Escaped Defect Analysis),即 遺漏問題分析 。不僅要分析為什麼問題被遺漏了,更要給出具體和切實可行的改進措施,以舉一反三,避免此類錯誤再次發生。隻有持續地改進,我們才能把前期測試工作做得越來越好,進而最大程度減少遺漏到後期測試階段的Bug數量。

繼續閱讀