透過建構測試案例來定位錯誤#

你常常可以透過撰寫適當的測試來精確定位甚至修正一個 bug。有人稱這種方法為 DDT(Defect-Driven Testing),缺陷驅動測試。這個方法包含三個步驟:重現、簡化、固化。

步驟一:建立可靠重現的測試案例#

首先,建立一個能可靠重現問題的測試案例。這意味著你需要明確指定:

  • Process(流程):觸發問題的操作步驟
  • Materials(素材):所需的測試資料

例如,載入某個檔案後按下特定按鍵組合導致應用程式崩潰,或是將某個負載平衡器放在應用程式前面導致使用者認證失敗。

步驟二:將測試案例簡化到最小#

第二步是將測試案例簡化到最小程度。有兩種方法:

  • 由下往上建構(Building up):從零開始逐步加入元素,直到 bug 首次出現
  • 由上往下精簡(Trimming down):從完整的大型測試案例中逐步移除元素,直到 bug 消失

在許多情況下,你可以結合兩種方法:先盡量移除無關部分,一旦你認為知道問題所在,就從頭建構一個最小測試案例。測試案例的簡化過程本身往往就能指向問題的根源。

步驟三:將測試案例固化為自動測試#

隔離出問題後,把握機會將測試案例轉化為對應的 unit testregression test

  • 如果錯誤位於獨立的程式碼部分,就加入 unit test
  • 如果是多個因素組合導致的問題,regression test 更為合適
  • 在 bug 尚未修復時執行測試,確認測試確實能捕捉到問題
  • 修復 bug 後再執行測試,確認測試通過

即使問題已經修復,加入測試仍然重要。它能防止同樣的錯誤在未來透過 merge conflict 或其他方式再次出現,也能捕捉到相關的錯誤。

善用測試覆蓋率工具#

使用 test coverage analysis 工具來了解哪些程式碼被測試覆蓋、哪些被跳過:

  • C/C++gcov
  • Java:JCov、JaCoCo、Clover
  • .NET:NCover、OpenCover
  • Pythoncoverage
  • JavaScriptblanket.js

重點回顧#

  • 建立可靠且最小化的測試案例,其簡化過程本身就能引導你找到錯誤根源
  • 將測試案例嵌入軟體中,作為 unit test 或 regression test 永久保存