選單

跨國家擴充測試資料:不變量與例外清單

從幾個地方擴到幾十個地方,難的不是數量而是差異的種類。本文說明不變量與例外清單怎麼分、資料產生為什麼要能重現、什麼時候該抽樣,以及新增一個地方時該跑哪些檢查。

發佈於

  • 測試策略
  • 擴充

跨國家擴充測試資料的難點,通常不在於把清單從幾個加長到幾十個,而在於每加一個就要多面對一組新的差異。如果每一組差異都得手寫一段測試,維護成本會以令人無法接受的速度成長。以下說明怎麼把這件事變成可累積的工作。

從幾個地方擴到幾十個地方,難在哪裡?

難在差異的種類會增加,而不是數量會增加。十個地方可能剛好都落在同一種規則下,於是看起來一切正常;到了三十個地方,突然出現幾種完全不同的結構,而原本的斷言假設全部失效。

第二個難點是組合爆炸。當每個地方都有若干可選欄位時,兩兩組合的數量成長得比地方數量快得多,於是不可能逐一窮舉。第三個難點是失敗的來源變得模糊:同一個紅燈可能來自資料本身、來自斷言假設,也可能來自某個地方的例外。

擴充階段 主要困難 應該優先做的事
少量地方 差異還看不出來 把共同規則寫成不變量
中量地方 開始出現例外 建立例外清單與負責人
大量地方 組合無法窮舉 轉向抽樣與風險排序
持續新增 前人例外無人理解 讓每條例外都附理由

理解這四個階段,可以避免在中量階段就急著引入複雜的產生器,也避免在大量階段還試圖窮舉。

階段的判斷也可以反過來用:如果團隊正在為某一類例外反覆撰寫特例,那通常代表不變量的切分方式需要重新檢視,而不是例外還不夠多。

把斷言分成不變量與例外清單

這是最有效的一個切分。不變量是所有地方都必須成立的事,例外清單則記錄那些不遵守某些不變量的地方與原因。兩者分開之後,新增一個地方就只是「通過全部不變量,並登記它的例外」。

不變量的例子包括:每個項目都能被選中、選中之後都能被還原、顯示名與儲存鍵不會互相汙染、匯出之後能再匯入。這些條件與地方的具體結構無關,因此可以穩定地套用到所有地方。

例外清單則要寫得足夠具體,讓後人能判斷它是否還成立:

  • 它不遵守哪一條不變量。
  • 為什麼不遵守,依據是什麼。
  • 從什麼時候開始,預計什麼時候重新檢視。
  • 誰負責判斷它是否仍然適用。

這份清單的價值會隨著時間增加。它同時是測試的輸入,也是新人理解系統的第一份讀物。

清單還有一個容易被忽略的用途:它是訓練材料。比起直接閱讀程式碼,先讀一份寫明「哪些地方不遵守哪些規則」的清單,能更快建立起對系統差異的整體認識。

資料產生要能重現

不能重現的測試資料等於沒有測試資料。當某個案例只在某一次執行中失敗,而沒有人能再讓它失敗一次,這個案例最終只會被標記為不穩定並被忽略——而它可能正好抓到了真問題。

因此資料產生要由固定的輸入決定,而不是由當下的時間或執行順序決定。實作上建議注意以下幾點:

  • 以固定的起始條件產生,讓同一組種子永遠得到同一批資料。
  • 產生的樣本要能對應到具名的案例,而不是只看得到一堆隨機值。
  • 記錄每一批資料的產生條件,失敗時可以直接重跑同一批。
  • 把產生器本身也納入版本管理,讓資料與程式同步演進。

要能重現還有一個附帶條件:樣本的存在理由要被寫下來。否則後人只會看到一堆長得差不多的資料,既不敢刪也不知道能不能改。數值相關的檢查該如何分層,可以對照號碼驗證的運作方式那篇。

什麼時候該抽樣而不是全量?

當全量的邊際價值低於它的執行成本時。抽樣不是偷懶,而是一種資源配置的決定,前提是你知道自己在抽什麼。

抽樣的正確做法是依風險分層,而不是隨機取幾個:

抽樣方式 適用情境 風險
依結構分層 差異來自欄位結構 分層定義錯就會漏掉一整類
依歷史故障分層 曾出錯的地方優先 新地方可能完全沒被覆蓋
依使用頻率分層 常見情境優先 罕見但嚴重的問題被延後發現
全量 改動涉及共用邏輯 執行時間長,但最能給出保證

判斷的關鍵是「這次改動碰到的是共用邏輯還是單點邏輯」。碰到共用邏輯時,全量的價值很高,因為一個錯誤會同時影響所有地方;只碰單點時,抽樣加上針對該點的專項案例通常就足夠。

分層還有一個實務要求:分層的定義要能被檢查。如果某個地方從未被任何一層涵蓋,那它其實是在抽樣之外,而不是被抽到。建議定期執行一次「哪些地方最近沒有被任何測試碰到」的查詢,把它當成健康指標。

新增一個地方要跑哪些檢查?

新增是擴充流程中最關鍵的一步,因為它同時引入資料與假設。把它固化成一份清單,可以避免每次都由不同的人用不同的標準處理。

  • 它的鍵在現有資料裡是否唯一,是否與既有鍵衝突。
  • 它需要哪些欄位,哪些欄位對它不適用。
  • 它是否違反任何一條不變量,若違反則登記例外。
  • 它是否需要一組專屬的樣本,樣本的理由是否已寫下。
  • 它的顯示名在各種語言下是否都已具備。
  • 它是否會影響依賴既有清單的彙總與分組。

這份清單的另一個用途是回顧:當某個地方被移除時,可以對照同一份清單逐項撤銷,而不會留下孤兒資料。

給開發者:把例外清單放進版本控制

例外清單不該只存在於某個人的筆記或對話裡。它必須與程式一起被版本管理,才能在改動時被看見、被討論、被要求附上理由。

  • 例外清單與不變量放在同一個版本庫,一起被審查。
  • 每一條例外都註明依據與檢視時間,讓過期能被發現。
  • 讓「不變量全部通過」成為合併前的必要條件,例外則需明確核准。
  • 定期移除已不成立的例外,避免清單成為沒人敢動的紀念碑。
  • 讓新增地方與新增例外走同一條流程,避免有人的路徑比較快。

本文的不變量敘述、例外條目與案例結構都是示意性質的合成內容,用來示範清單可以長成什麼樣子,並非真實系統的測試報告、缺陷紀錄或需求文件。要把這些原則套回具體的選擇流程,可以讀國家選擇欄位測試;而資料本身的保鮮問題,見國家資料新鮮度。

下一步

把你目前所有的地方隨便挑一個,寫出它不遵守的那條規則並附上理由。若寫不出來,那條規則其實是通用的,應該被提升為不變量。要列出完整的地方清單與欄位樣貌,可以從國家與地區目錄開始。

繼續閱讀

各國地址與身分資料格式相關文章