如何用最少的測試測出強健的系統:Combinatorial Test Design

Sam Huang
Gogolook Tech
Published in
9 min readJun 15, 2020

By Sam Huang

前言

身為 Gogolook 的軟體工程師,平時除了根據商業需求快速開發功能外,軟體品質也一直是 Gogolook 非常注重的項目。我們根據不同階段的產品,設計了不同的 DoD(Definition of Done)以確保產出的軟體品質,不論在哪個階段的 DoD,Unit Test 與 Integration Test 都是最基本的工作。但過去一直都有一個困擾,儘管專案都已經有 80% Line Coverage、75% Branch Coverage 與大量的測試案例,在某些情境下還是會產生意想不到的 Bug,一味地增加測試案例也不是辦法,因此開始尋找高效率的測試方法,如果你也有「不知道寫多少測試才足夠」的困擾,那 Combinatorial Test Design 或許可以解決你的困擾。

Combinatorial Test Design 是什麼?

Combinatorial Test Design(CTD)最早是在 1980 年代中期,被提出來使用在軟體系統的測試上,最早是以正交法(Orthogonal Array)來實作 CTD。CTD 的目的是希望從所有可能的測試案例中,找出最少的測試案例,而這些測試案例可以涵蓋在特定層級下的所有互動行為,藉此達到風險控制與時間成本之間的平衡。以往我們在做測試時會面臨以下幾個問題:

  1. 無法窮舉所有測試案例。
  2. 測試案例越多越好的迷思。
  3. 手動設計案例時,通常只會修改小部分變數來試圖涵蓋更多的系統範圍,使得測試案例沒有發揮最大效率。

所以 Combinatorial Test Design 的目標便是解決以上三個問題,透過大量地降低測試案例數量與確保系統互動的涵蓋範圍,使我們的時間運用得更有效率以及更清楚地控制風險。IBM 在 2012 年時也分享了一個實際運用在專案上的經驗,在開發團隊與測試團隊共同協作下,從總數 7800 個潛在測試案例中挑選了 21 個測試案例實作,最後不僅大量縮短測試週期並額外多發現了 20 個 Bugs,也在接下來的兩年內系統沒有服務中斷的發生。

測試的排列組合

在開始說明 CTD 的步驟前請問大家以下的問題。

在做測試時,我們需要測試所有排列組合嗎?

相信大家很難直接給出一個明確的答案,也就是多少的排列組合對於系統來說是足夠的,這個問題在 NIST 的研究中有給出了答案。表格中是 NIST 統計從 1999 年至 2004 年,在不同領域的系統中,軟體發生錯誤時是由多少變數導致而成。從表格中可以發現,軟體的錯誤有 90% 是三個以下的變數造成。而在系統較為單純的醫療設備(Medical Devices)上,甚至達到 99% 的錯誤涵蓋率。換句話說,只需測試三個變數間的所有排列組合(3-way Combinations),便可以避免掉 89% ~ 99% 的系統錯誤。

範例:電商系統

步驟一:確認變數

首先確認待測對象後,列出所有參與的變數。

電商系統中可能有以下這些變數:

  • Availability
  • Payment Method
  • Carrier
  • Delivery Schedule
  • Export Control

步驟二:確認變數值

確認所有變數後,列出每一個變數在系統或是函式上所有可能數值。若型別是 Boolean 則為 True 或 False;若型別是 Enum 則列出所有選項;若型別是 Integer、Float、String 這類沒有明確範圍的變數,則可參考 Software Testing 中 Input Space Partitioning 的方法,來決定需要列出哪些數值。

電商系統中可能有以下這些變數數值:

將所有可能的數值列出來後可以算出一共有 4 x 3 x 3 x 4 x 2 = 288 種排列組合,也就是 288 個潛在測試案例。假設系統上,當 Payment = Paypal 且 Delivery Schedule = One Day 時會有一個 Bug 產生,表示在 288 個測試案例中有 24(4 x 1 x 3 x 1 x 2 = 24) 個測試案例都可以抓到同一個錯誤,而這 24 個測試案例中,有很大的比例是不需要測試的重複案例,這些重複測試到的案例便是我們可以刪減與提高效率的部分。這種兩個變數參與下產生的互動稱為 Level 2 Interaction,若是三個變數參與下的互動則稱為 Level 3 Interaction,依此類推。根據 NIST 的研究報告,89% ~ 95% 的錯誤是由三個以下的變數造成,因此,我們只需做到 Level 3 Interaction 的所有排列組合(3-way Combinations),就已具備相當的系統穩定度。

步驟三:設定限制條件與規則

限制條件(Restrictions)有兩種類型,一種是 Include 條件另一種是 Exclude 條件,目的是用來在領域模型上增加一些條件,在產生測試案例時,可以根據設定的條件來包含或排除某些組合,電商系統中可能會有下面條件:

  1. Include:若 Payment 選擇 Gift Voucher,則 Carrier 必須是 Mail,因為商業上的策略,目前禮券只能搭配郵遞一起使用。
  2. Exclude:若 Carrier 選擇 FedEx 快遞,則 Delivery Schedule 則不可能為 Over 10 Working Days,因為快遞三天內便會將貨物送達。

步驟四:產生測試案例

目前已有些現成的工具能協助我們產生測試計劃,只要將步驟一至步驟三的資料輸入工具後,工具就會自動跑出結果,而我們只需將工具產生的結果實作成測試案例即可,以下提供幾個工具供大家參考:

  • ACTS:免費。由 NIST 所提供的工具,寫信給承辦人後可以得到下載連結。
  • PICT:免費。由微軟提供的 Command Line Tool。
  • Hexawise:付費。功能完整,也有團隊協作功能,也可以自動產生 Gherkin 腳本,若是有執行 BDD 或是 SBE 的團隊很適合嘗試看看。
  • Pairwiser:線上版免費。簡單的操作就可以產生案例,也有圖表可以清楚了解測試數量與涵蓋率的關係。

以 Pairwiser 示範操作流程:

設定所有 Parameters 及 Constraints。

選擇 2-way 方式產生 Test Cases。

Pairwiser 的產生結果
2-way 下測試案例的數量與互動涵蓋率的關係圖

最後產生的結果可以發現,在 Level 2 Interaction 的情況下,我們只需要 18 個測試便能涵蓋所有 2-way Combinations,在每一項測試案例中皆可發揮最高的測試效率。

例如:測試案例 #1 其實同時在測試多個變數與數值之間的組合,未來的測試案例則會盡量避免再測一次。

  • (Availability: Not in Stock, Payment: Gift Voucher)
  • (Payment: Gift Voucher, Carrier: Mail)
  • (Payment: Gift Voucher, Export Control: False)

透過提高測試案例的效率,也從總數 288 個排列組合大幅降低至 18 個,大約節省了 94% 的測試案例。若是更嚴謹地設定限制條件,則可能再降低測試案例的數量。

工商時間

偷塞一個工商時間,以防大家看完結論就不繼續往下滑惹。

Gogolook 在 2020 年不畏 COVID-19 的疫情影響持續招募中,如果你/妳對於軟體品質有相當的要求或是敏捷開發的實踐有獨到的看法,Gogolook 是一個可以讓你/妳有機會發揮的地方。後端團隊也計劃在幾個月內完成所有雲端資源的 IaC 化,期望一個指令就可以開始泡茶聊天,等它自己完成 Database Create/Restore, Create Kubernetes Cluster、Deploy Services 、Routing 等等工作並開始 Serve 流量,我們需要你/妳一起來完成這個令人興奮的任務。

職缺內容請看這邊 https://whoscall.com/zh-TW/careers/joblist/

也可以直接聯絡 HR | Jennifer Chuang: jennifer.chuang@gogolook.com

來電辨識第一品牌 Whoscall:https://whoscall.com/zh-TW/

信貸比較神器 Roo 貸鼠先生:https://roo.cash/

結論

Combinatorial Test Design 可以實踐在各個層級的測試中,軟體開發工程師可以使用在 Unit Test,測試工程師可以使用在 System Integration Test。透過聰明且有理論基礎的方法,讓你節省大量的測試時間又掌控系統風險,系統化地設計測試計劃,也使我們清楚了解測試了哪些案例,而節省下來的時間可以拿來沖杯咖啡或是投履歷給 Gogolook 。如果過去也有測試數量方面的困擾,推薦你嘗試看看 Combinatorial Test Desgin。

參考資料

  1. Combinatorial Test Design
  2. Combinatorial Test Design: Who needs it and what’s it good for?
  3. The value of CTD
如果你喜歡這邊文章,歡迎分享給其他的測試苦手。
希望你可以拍拍手 👏 給小弟一些鼓勵,只需要按著 10 秒就能拍完 50 下囉!

--

--