不只是 TDD #2, 兩個版本自我驗證 + 執行期驗證

不只是 TDD #2, 兩個版本自我驗證 + 執行期驗證

問題與答案 (FAQ)

Q&A 類別 A: 概念理解類

Q1: 什麼是「不只是 TDD」的觀念?

  • A簡: 超越單元測試,結合兩版本自我驗證與執行期驗證,全面提升正確性與可維護性。
  • A詳: 「不只是 TDD」強調 TDD 不僅止於撰寫單元測試,而是擴展到完整的品質保障策略:先建構保守且可靠的基準版本作為對照,再以大量靜態與動態測試進行兩版本輸出比對,並於執行期透過斷言與條件式編譯加入Fail-Fast防線。此法能兼顧正確性、效能與可維護性,並在重構或最佳化時降低風險。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q2, A-Q5, B-Q4

Q2: 為什麼 TDD 不僅是寫單元測試?

  • A簡: 單元測試有限,需輔以自動產生測資與執行期斷言,涵蓋未知情境。
  • A詳: 單元測試常侷限於已知情境與有限案例,無法覆蓋各種極端與實際運行的錯誤情境。將 TDD 擴展至兩版本比對(以保守版為基準)與執行期驗證(Fail-Fast 斷言、狀態檢查、條件編譯)可及時偵測演算法錯誤與不一致,並持續在實務環境中驗證行為,讓品質保證從開發期延伸至運行期。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q1, A-Q10, B-Q9

Q3: 什麼是保守版本(Baseline/Conservative Version)?

  • A簡: 易實作、可驗證正確性但未最佳化的參考解,作為測試預言機。
  • A詳: 保守版本指以最容易、最直觀的方式先解決問題的實作,不求最佳時間複雜度,先確保正確。它扮演測試預言機(Oracle),用於比對新版本輸出。像排序中以泡泡排序代替快速排序;在最短迴文中用從右到左尋找、再核對回文的方式。保守版能穩定產生正確答案,為大量自動驗證打下基礎。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q4, A-Q5, B-Q1

Q4: 保守版本與最佳化版本的差異是什麼?

  • A簡: 保守版重正確易實作;最佳化版重效能。前者常充當驗證預言機。
  • A詳: 保守版多以簡單直觀的演算法達成正確性,例如 O(n^2) 的泡泡排序;最佳化版則追求更佳的時間/空間複雜度,如 O(n log n) 的快排。開發流程上,先用保守版建立正確基準,再以最佳化版替換關鍵路徑,並用兩版本比對保障行為一致,降低回歸風險,提升重構信心。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q3, B-Q14, C-Q1

Q5: 什麼是兩個版本自我驗證(Two-version self-validation)?

  • A簡: 以保守版為基準,新舊版本對同組測資比對輸出,驗證一致性。
  • A詳: 兩版本自我驗證做法是同時維護保守版與最佳化新版本。對於靜態與動態生成的大量測資,以兩者分別運算並比對結果。若一致,表示新版本在該測資下行為正確;不一致時可快速聚焦於新改動。此策略降低未知情境風險,是重構、提效與演算法迭代的安全網。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q4, C-Q2, D-Q1

Q6: 什麼是動態測試案例產生(自動化測資)?

  • A簡: 程式自動隨機或系統化生成輸入,擴大涵蓋率,降低人工成本。
  • A詳: 動態測試案例產生會由程式自動生成大量輸入(如長度、字元分佈皆隨機),或以系統化策略探索輸入空間,快速擴大測試涵蓋率。配合保守版作為預言機,可自動取得期待輸出,用於驗證新版本。此法能發現極端值與邊界條件,常見於 fuzzing 與隨機測試。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q3, B-Q13, C-Q3

Q7: 靜態測試與動態測試的差異?

  • A簡: 靜態手工精選極端案例;動態大量隨機生成,互補驗證品質。
  • A詳: 靜態測試由工程師精挑常見與高風險案例(如超長字串、重複字元),能精確檢驗已知風險;動態測試透過程式大量生成隨機或系統化輸入,能探勘未知情境。兩者互補:靜態保證關鍵路徑,動態擴大未知覆蓋;搭配兩版本比對可形成高信心的驗證體系。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: A-Q6, C-Q4, D-Q2

Q8: 為什麼要先建立「可敬的對手」?

  • A簡: 讓機器以可靠基準自動產生挑戰,逼出新版本的缺陷與極限。
  • A詳: 「可敬的對手」即保守版,它能穩健產生正確輸出,成為新版本的鏡像對照。藉由它自動生成大量測資並比對結果,像 AlphaGo 自我對弈般累積經驗,可快速暴露新演算法的盲點與回歸。此策略將人力由造案與驗算轉為分析與優化,提升學習與迭代效率。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q3, A-Q5, B-Q12

Q9: 什麼是 Fail-Fast 原則?

  • A簡: 一旦偵測到異常狀態,立即停止並回報,以最低成本修正。
  • A詳: Fail-Fast 強調在最靠近錯誤發生點就中止流程並曝露問題,而非延後處理。透過執行期斷言、前置條件檢查、狀態一致性驗證等手段,能縮小除錯範圍、保護資料一致性。此原則與條件式編譯相輔,開發期全面開啟、正式版依需要控制開關。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q10, B-Q9, C-Q6

Q10: 單元測試與執行期驗證有何差異?

  • A簡: 單元測試偏開發期黑箱;執行期驗證透過斷言檢查內部不變式。
  • A詳: 單元測試主要在開發與建置階段執行,驗證對外行為是否符合規格;執行期驗證則在程式運行時檢查內部前後置條件與不變式(如統計資料與實際狀態一致)。兩者互補:單元測試覆蓋已知需求,執行期驗證攔截環境或資料驅動的隱蔽錯誤。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: A-Q9, B-Q7, B-Q10

Q11: 什麼是條件式編譯與自訂 LOCAL_DEBUG?

  • A簡: 以編譯條件控制除錯碼納入與否,兼顧效能與可維護性。
  • A詳: 條件式編譯透過編譯旗標(如自訂 LOCAL_DEBUG)包覆除錯、記錄、斷言等輔助程式碼。開發與本機調試時開啟,提交或正式環境關閉,避免影響效能或評測平台行為(如 LeetCode)。這讓同一份程式可在不同場景平衡可觀測性與效能。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: B-Q8, C-Q5, D-Q4

Q12: 覆寫 ToString() 對除錯有何價值?

  • A簡: 快速在偵錯器顯示物件關鍵狀態,提升問題定位效率。
  • A詳: 覆寫 ToString() 可自訂物件在偵錯器顯示的文字,將核心欄位以可讀格式呈現,輔助理解狀態變化與邏輯錯誤。配合條件式編譯可避免在提交或正式版產生額外成本,保持觀測性與效能的平衡,常用於演算法狀態與遊戲盤面可視化。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q15, C-Q7

Q13: 在演算法學習中先寫保守版的核心價值是什麼?

  • A簡: 先保正確、建預言機,再逐步最佳化,降低迭代風險。
  • A詳: 新問題常在正確性與設計未定時就追求最佳化,風險高。先寫保守版能快速建立正確基準與測試預言機,之後任何最佳化與重構都可用兩版本比對驗證,將風險降至可控範圍。此策略也促進對問題結構的理解,為後續選擇更佳演算法鋪路。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q3, A-Q5, B-Q14

Q14: 什麼是執行期驗證(Runtime Verification)?

  • A簡: 於程式運行時檢查不變式與前後置條件,及早攔截錯誤。
  • A詳: 執行期驗證將各種檢查內嵌於主程式,監控運行過程中的狀態一致性與合法性,例如步驟位置合法、手牌可用、統計值吻合實際盤面。當違反時立即告警或中止。以條件式編譯控制啟用範圍,可在研發與測試期全面開啟,正式環境視需求調整。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q9, B-Q7, C-Q6

Q15: 在重構與微服務遷移中兩版本比對的重要性?

  • A簡: 確保外部行為不變,讓重構更安全可控,可漸進上線。
  • A詳: 拆分單體至微服務或重構內部模組時,目標是改善內部品質而不改變可見行為。以舊系統為基準,在運行期對同請求進行鏡像比對,驗證輸出一致;再搭配斷言檢查內部不變式。此作法支援灰度/金絲雀上線與快速回滾,顯著降低變更風險。
  • 難度: 中級
  • 學習階段: 進階
  • 關聯概念: B-Q11, C-Q8, D-Q10

Q&A 類別 B: 技術原理類

Q1: 保守版最短迴文演算法如何運作?

  • A簡: 由右往左尋找與首字相同位置,檢查前綴是否為回文,再補齊反轉字串。
  • A詳: 原理說明:對字串 s 長度 n,自最右端向左掃描,找到 s[right] 等於 s[0] 的位置,呼叫 check 驗證 s[0..right] 是否為回文;若是,padtext 將 s[right+1..n-1] 反轉後加到最前得到最短迴文。流程:掃描→檢查→補字。核心組件:check(雙指針比對)、padtext(子串反轉拼接)。此法易實作但效能非最優。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q3, B-Q2, C-Q1

Q2: check() 與 padtext() 在保守版中的機制是什麼?

  • A簡: check 雙向收斂驗證回文;padtext 反轉尾段並前置,形成最短迴文。
  • A詳: 技術原理:check 採 i 與 right-i 的雙指針由外向內收斂,比對字元不相等即回傳 false,全通過則為回文。padtext 取 s[right+1..] 反轉後加到 s 前方。流程:1) check 驗證前綴 2) 成功後 padtext 產出結果。核心組件:索引計算、子串切割、反轉與拼接。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q1, C-Q1

Q3: 隨機字串產生器 GenRandomText 如何運作?

  • A簡: 隨機決定長度,再從 a-z 隨機挑字,重複 run 次輸出。
  • A詳: 原理說明:以 Random 先抽樣長度(0~maxlength),再迭代每一位由 26 個小寫字母隨機挑選,組合成字串。流程:初始化亂數→外層迴圈產生 run 筆→內層迴圈填入隨機字元→yield 回傳。核心組件:隨機數產生器、字元池、可列舉產生器,確保涵蓋多樣長度與內容。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: A-Q6, C-Q3, D-Q2

Q4: 兩版本比對的測試執行流程為何?

  • A簡: 初始化新舊版本,對每組輸入呼叫兩邊函式,Assert 比對輸出。
  • A詳: 技術原理:以保守版作 Oracle,新版作待驗。流程:1) 測試初始化建立 SubmitHost 與 BasicSolution 2) 準備靜態與動態輸入 3) 迴圈輸入兩邊計算 4) 以 Assert.AreEqual 檢查一致 5) 記錄不一致樣本。核心組件:測試框架(MSTest)、斷言 API、資料生成器,支援大量自動驗證。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: A-Q5, C-Q2, D-Q1

Q5: 如何設計「涵蓋率提升」的資料生成管線?

  • A簡: 混合靜態極端與動態隨機,控制長度分布,保留失敗種子。
  • A詳: 原理:以多來源擴大覆蓋率。流程:1) 靜態集選邊界與極端值(超長、全同字元、接近回文)2) 動態集用不同種子生成多分布長度與字元 3) 對失敗樣本固化為靜態 4) 週期性重播所有樣本。核心組件:亂數種子管理、分層抽樣策略、資料持久化機制。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q7, B-Q13, C-Q4

Q6: ZumaGame 的 AssertStatisticData 機制是什麼?

  • A簡: 以字典統計顏色計數,與盤面實際狀態比對,不一致即拋錯。
  • A詳: 技術原理:以字典維護 R/Y/B/G/W 顏色累計數,遍歷盤面節點累加,與當前統計欄位對照。流程:1) 重建統計 2) 逐色比對 3) 不一致即丟出例外。核心組件:盤面資料結構、統計字典、異常處理。此為運行期不變式檢查,能快速定位狀態腐化。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q14, B-Q7, C-Q9

Q7: 在 ApplyStep 中插入斷言的流程是什麼?

  • A簡: 先檢查前置條件,再執行步驟,前後各驗統計一致性。
  • A詳: 技術原理:以前後置條件與不變式確保操作合法。流程:1) 前置檢查位置與手牌可用 2) 執行插入或計數變更 3) 執行連鎖消除等邏輯 4) 兩次 AssertStatisticData 保證一致性。核心組件:前置條件驗證、狀態轉換、斷言回饋,支援 Fail-Fast。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q10, A-Q14, C-Q6

Q8: Conditional Compilation(LOCAL_DEBUG)的技術架構?

  • A簡: 自訂編譯旗標包覆除錯碼,開發啟用、提交剃除,避免影響效能。
  • A詳: 技術原理:以 #define LOCAL_DEBUG 與 #if(LOCAL_DEBUG) 包裹調試程式碼(ToString、斷言、記錄)。流程:1) 本機定義旗標 2) 編譯器僅保留對應區塊 3) 提交或正式環境不定義即剃除。核心組件:編譯器條件處理、觀測碼隔離、環境差異控制。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: A-Q11, C-Q5, D-Q4

Q9: Fail-Fast 在系統設計中如何落地?

  • A簡: 在關鍵轉換設前後置檢查與不變式斷言,立即中止異常流程。
  • A詳: 技術原理:對各層(演算法步驟、狀態機、資料管線)加入前置條件與不變式檢查,違反即中止並記錄。流程:辨識關鍵點→定義不變式→加入斷言→路徑測試。核心組件:斷言框架、例外策略、日誌與可視化。成效:縮小除錯半徑、保障資料正確。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q9, B-Q7, C-Q6

Q10: 單元測試的黑箱與白箱界定為何?

  • A簡: 對外介面黑箱驗證為主,可搭配白箱觀測提高可診斷性。
  • A詳: 技術原理:單元測試多以公開介面為黑箱驗證,但可藉依賴注入、觀測點、內部狀態快照等實踐部分白箱觀測。流程:設計可測性→撰寫對外案例→必要時揭露觀測點。核心組件:測試替身、斷言、可觀測性鉤子。結合執行期斷言達至內外一致驗證。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: A-Q10, C-Q2

Q11: 微服務重構中的運行期鏡像比對架構是什麼?

  • A簡: 同步將請求送至新舊服務,離線比對回應差異,逐步放量。
  • A詳: 技術原理:流量鏡像或雙寫策略將同一請求送往新舊實作,收集回應比對差異。流程:流量分流→收集→比對→告警→修正→放量。核心組件:流量鏡像、差異比對器、告警監控、開關策略(灰度、金絲雀)。保證行為等價後再切換生產流量。
  • 難度: 高級
  • 學習階段: 進階
  • 關聯概念: A-Q15, C-Q8, D-Q10

Q12: 以保守版作為測試預言機的理論基礎是什麼?

  • A簡: 以已知可靠實作充當 Oracle,比對等價關係,降低 Oracle 問題。
  • A詳: 技術原理:測試 Oracle 問題是難以知曉正確輸出的難題。以保守版(已驗證正確)作參考,建立等價關係:對同輸入輸出應一致。流程:驗證保守版→產生輸入→比對輸出。核心組件:基準實作、比對器、種子管理。也可結合變形測試補強。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q5, B-Q4, B-Q13

Q13: 隨機測試(Fuzzing)的流程與風險控制?

  • A簡: 以種子生成大量隨機輸入,需可重現、限界與去重以控風險。
  • A詳: 技術原理:以亂數種子驅動輸入產生,探索未知空間。流程:設計分布→生成→執行→收集失敗→固化用例→再迭代。核心組件:種子記錄、邊界控制(長度、字元集)、失敗最小化與去重。風險控管:確保重現性、限制資源、避免無意義樣本淹沒。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q6, B-Q5, D-Q2

Q14: 最佳化演算法的漸進替換與回歸保護機制?

  • A簡: 以旗標漸進切換,持續兩版本比對,回歸失敗即回滾修正。
  • A詳: 技術原理:以 Feature Flag/策略路由逐步導入新演算法,保留保守版並行。流程:雙實作上線→鏡像比對→小流量放量→監控→異常回滾。核心組件:開關管理、比對報告、監控與告警。確保每一步皆有回歸保護,降低切換風險。
  • 難度: 中級
  • 學習階段: 進階
  • 關聯概念: A-Q4, B-Q11, D-Q8

Q15: ToString 對 Debugger 可視化的技術要點?

  • A簡: 輸出關鍵狀態且避免重運算,搭配條件編譯降低正式成本。
  • A詳: 技術原理:覆寫 ToString 將狀態摘要化(如盤面節點序列),利於斷點時快速理解。流程:挑選關鍵欄位→格式化輸出→以 LOCAL_DEBUG 包覆。核心組件:字串建構、條件式編譯、效能考量。避免重運算或副作用,確保僅在調試場景啟用。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q12, C-Q7

Q&A 類別 C: 實作應用類(10題)

Q1: 如何在 C# 建立 BasicSolution 作為保守版?

  • A簡: 以右掃+check+padtext策略,先保正確,提供對照基準。
  • A詳: 步驟:1) 建立類別 BasicSolution,實作 ShortestPalindrome 2) 由右往左尋找與首字相同索引 right 3) 寫 check 驗證 s[0..right] 是否回文 4) 寫 padtext 反轉尾段前置。關鍵程式:check 雙指針比對;padtext 使用 Substring+Reverse。注意:優先正確性,建立後即能充當 Oracle。最佳實踐:清楚命名、封裝輔助函式。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q1, B-Q2

Q2: 如何撰寫 MSTest 單元測試比對兩版本?

  • A簡: 初始化新舊實例,遍歷資料集用 Assert.AreEqual 比對輸出。
  • A詳: 步驟:1) 在 [TestInitialize] 建立 SubmitHost 與 BasicSolution 2) 準備靜態與動態測資列舉 3) 於 [TestMethod] 迴圈呼叫兩邊 ShortestPalindrome 4) 以 Assert.AreEqual 驗證一致。關鍵程式:TestClass/TestMethod 屬性、Assert API。注意:記錄不一致輸入,保留為靜態案例。最佳實踐:將生成與比對拆函式,提高重用。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: B-Q4, C-Q4

Q3: 如何實作 GenRandomText 產生動態測資?

  • A簡: 以亂數決定長度與字元,yield 多組字串,支援大樣本測試。
  • A詳: 步驟:1) 準備字元池 “abcdefghijklmnopqrstuvwxyz” 2) 使用 Random 抽長度 0..maxlength 3) 逐位以 rnd.Next(26) 取字元 4) 重複 run 次數並 yield。關鍵片段:for i<rnd.Next(maxlength+1) append text[rnd.Next(26)]。注意:保存種子以便失敗重現。最佳實踐:限制長度上限,避免測試耗時失控。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: B-Q3, B-Q13

Q4: 如何將動態測資轉成靜態 .csv/.xml 資料源?

  • A簡: 將動態產生輸入與預期輸出固化,納入版本控制重播回歸。
  • A詳: 步驟:1) 以保守版計算每筆動態輸入之期望輸出 2) 輸出成 csv: input,expected 或 xml 結構 3) 測試讀檔餵入 Assert 比對 4) 失敗案例追加持久化。關鍵設定:檔案編碼、路徑配置。注意:維護資料一致性與去重。最佳實踐:分群管理邊界與隨機集,定期回放。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q5, D-Q3

Q5: 如何用條件式編譯加入除錯輔助且不影響提交?

  • A簡: 以 #define LOCAL_DEBUG 包覆 ToString/斷言碼,提交時不定義。
  • A詳: 步驟:1) 檔頭宣告 #define LOCAL_DEBUG(僅本機) 2) 用 #if (LOCAL_DEBUG) 包覆調試碼(覆寫 ToString、統計檢查、記錄) 3) 提交前移除或關閉旗標。關鍵設定:編譯條件、檔案範圍。注意:避免在調試碼中產生副作用。最佳實踐:統一常數與說明註解,防誤用。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: B-Q8, A-Q11

Q6: 如何在演算法核心安插 Fail-Fast 檢查點?

  • A簡: 針對前置條件與不變式插入斷言,違反即拋錯終止流程。
  • A詳: 步驟:1) 辨識前置條件(索引、資源可用) 2) 定義不變式(統計一致、單調性等) 3) 關鍵步驟前後呼叫檢查函式 4) 異常即 throw。程式片段:if (pos>=Count) throw; 檢查後 AssertStatisticData()。注意:以條件式編譯控制環境。最佳實踐:訊息清楚、可定位問題。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q9, B-Q7

Q7: 如何覆寫 ToString 以利調試與記錄?

  • A簡: 組合重要欄位成摘要字串,於偵錯器即時觀察物件狀態。
  • A詳: 步驟:1) 選擇重點欄位(如節點顏色與計數) 2) 建立 StringBuilder 逐一拼接 3) 回傳簡潔可讀字串 4) 用 LOCAL_DEBUG 包覆。關鍵:避免重運算與副作用。注意:輸出長度應控制,避免淹沒訊息。最佳實踐:格式約定一致,利於日誌解析。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q15, A-Q12

Q8: 重構時如何進行執行期新舊版本 Side-by-side 比對?

  • A簡: 同步處理請求,收集輸出差異與統計,逐步放量驗證一致。
  • A詳: 步驟:1) 以代理層或中介軟體鏡像請求至新舊實作 2) 非侵入收集回應 3) 差異比對與告警 4) 將不一致樣本固化為測試 5) 驗證穩定後逐步導流。關鍵設定:超時隔離、日誌關聯ID。注意:避免回寫副作用。最佳實踐:開關控制、可回滾策略。
  • 難度: 高級
  • 學習階段: 進階
  • 關聯概念: B-Q11, D-Q10

Q9: 如何為 ZumaGame 維護統計一致性檢查?

  • A簡: 每次步驟前後重建統計,與快取值比對,不一致立即告警。
  • A詳: 步驟:1) 建立顏色計數字典初值 2) 依盤面節點累計 3) 與 CurrentBoardStatistic 對照 4) 不一致 throw 例外 5) 在 ApplyStep 前後各呼叫。關鍵:資料結構一致、遍歷正確。注意:在 LOCAL_DEBUG 下啟用。最佳實踐:將檢查封裝函式化,易於重用。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q6, B-Q7

Q10: 如何設計測試集以涵蓋極端與長度邊界?

  • A簡: 精選邊界與極端樣本,搭配長度分布控制的隨機生成。
  • A詳: 步驟:1) 靜態:空字串、單字元、全相同、幾乎回文、超長 2) 動態:控制長度分布與字元集 3) 將失敗樣本固化 4) 分群標記案例類型。關鍵:長度上限、資源限制。注意:測試時間與穩定性平衡。最佳實踐:每日回放核心集,週期回放全量集。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q5, B-Q13

Q&A 類別 D: 問題解決類(10題)

Q1: 兩版本結果不一致怎麼辦?

  • A簡: 固化失敗樣本,重放定位差異,最小化輸入以縮小除錯範圍。
  • A詳: 症狀:Assert 比對失敗。原因:新演算法邏輯錯誤、邊界處理不當。解決:1) 固化失敗輸入 2) 對兩版加日誌與斷言 3) 二分縮短輸入重現 4) 修正並補測。預防:持續鏡像比對、小步提交、增加邊界用例庫。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q4, C-Q4

Q2: 隨機測試偶發失敗如何診斷?

  • A簡: 保留亂數種子與輸入,重現環境,逐步縮小並固化為靜態。
  • A詳: 症狀:Fuzz 測試偶爾紅燈。原因:不可重現的種子、環境差異、非決定性邏輯。解決:1) 記錄種子與輸入 2) 固定種子重跑 3) 切換單執行緒或固定時序 4) 修正並固化用例。預防:標準化執行環境、記錄關鍵上下文。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q13, C-Q3

Q3: 測試生成過慢影響研發節奏怎麼優化?

  • A簡: 分層測試集、限制長度與次數、快取結果、並行與夜間全量。
  • A詳: 症狀:本機測試過久。原因:輸入過長、次數過多、重複運算。解決:1) 快速集(小樣本)本機 2) 全量集 CI 夜跑 3) 限制 maxlength 與 run 4) 快取保守版輸出。預防:建立測試分層策略與時限控制。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: B-Q5, C-Q10

Q4: 在 LeetCode 提交遇到除錯碼影響效能怎麼辦?

  • A簡: 使用 LOCAL_DEBUG 包覆除錯碼,提交時確保未定義以剃除。
  • A詳: 症狀:提交效能差或輸出多餘資訊。原因:調試碼未剃除。解決:1) 確認未定義 LOCAL_DEBUG 2) 檢查 #if 區塊 3) 必要時移除冗餘輸出。預防:統一以條件式編譯管理所有調試碼,提交前檢查。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q8, C-Q5

Q5: 運行期斷言導致程式崩潰如何處置?

  • A簡: 在開發期保留 Fail-Fast,正式環境降級處理與告警記錄。
  • A詳: 症狀:正式版斷言拋例外中止。原因:無分環境策略。解決:1) 以條件式編譯或設定關閉硬中止 2) 改為記錄與告警 3) 釐清根因後修復。預防:製定環境等級策略:開發 Fail-Fast、測試強告警、正式柔性處理。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q9, B-Q9

Q6: 統計資料與實際狀態不一致怎麼排查?

  • A簡: 於每個變更點前後檢查,定位最早不一致處並最小化案例。
  • A詳: 症狀:AssertStatisticData 失敗。原因:狀態更新漏步、邊界溢出、併發問題。解決:1) 在所有更新點前後加檢查 2) 二分法縮小步驟 3) 檢查資料結構迭代邏輯 4) 修正並加回歸測試。預防:封裝狀態修改、單一責任原則。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q6, C-Q9

Q7: 單元測試不足導致回歸缺失怎麼補救?

  • A簡: 擴充靜態邊界集、引入動態生成、加入兩版本比對流程。
  • A詳: 症狀:最佳化後出現回歸。原因:測試涵蓋不足。解決:1) 回收真實失敗案例入靜態庫 2) 增加隨機測資 3) 導入保守版比對 4) 建立回歸套件。預防:每次修復先加案例後修程式,持續回放。
  • 難度: 初級
  • 學習階段: 核心
  • 關聯概念: A-Q7, B-Q5

Q8: 最佳化版效能未提升或變慢的原因?

  • A簡: 算法不適合輸入分布、常數成本高、實作細節拖累快取局部性。
  • A詳: 症狀:新版本比舊版慢。原因:實際輸入不符假設、分支錯誤、記憶體配置過頻。解決:1) 以基準測試分析瓶頸 2) 針對熱路徑優化 3) 確認資料結構與快取友善。預防:以小步驗證效能、建立性能回歸測試。
  • 難度: 中級
  • 學習階段: 進階
  • 關聯概念: B-Q14, C-Q10

Q9: Fuzz 測試產生重複或低質案例怎麼改善?

  • A簡: 去重與覆蓋率導向的抽樣,保存高價值失敗種子。
  • A詳: 症狀:大量重複輸入,收斂慢。原因:隨機策略單一、無去重機制。解決:1) 以集合去重 2) 調整分布與長度 3) 引入覆蓋率或差異導向 4) 保存與優先播放失敗種子。預防:定期清理低價值樣本、調參。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q13, C-Q3

Q10: 重構跨服務引入行為變更如何追蹤?

  • A簡: 流量鏡像與差異比對,加入告警與回滾,固化不一致案例。
  • A詳: 症狀:拆分後回應差異。原因:邊界條件處理差異、序列化不一致。解決:1) 鏡像請求雙寫 2) 差異報表與告警 3) 小流量放量 4) 快速回滾 5) 補齊契約測試。預防:契約先行、等價性測試、漸進上線策略。
  • 難度: 高級
  • 學習階段: 進階
  • 關聯概念: B-Q11, C-Q8

學習路徑索引

  • 初學者:建議先學習哪 15 題
    • A-Q1: 什麼是「不只是 TDD」的觀念?
    • A-Q2: 為什麼 TDD 不僅是寫單元測試?
    • A-Q3: 什麼是保守版本(Baseline/Conservative Version)?
    • A-Q4: 保守版本與最佳化版本的差異是什麼?
    • A-Q5: 什麼是兩個版本自我驗證(Two-version self-validation)?
    • A-Q7: 靜態測試與動態測試的差異?
    • A-Q9: 什麼是 Fail-Fast 原則?
    • A-Q10: 單元測試與執行期驗證有何差異?
    • A-Q11: 什麼是條件式編譯與自訂 LOCAL_DEBUG?
    • A-Q12: 覆寫 ToString() 對除錯有何價值?
    • B-Q1: 保守版最短迴文演算法如何運作?
    • B-Q2: check() 與 padtext() 在保守版中的機制是什麼?
    • B-Q3: 隨機字串產生器 GenRandomText 如何運作?
    • C-Q1: 如何在 C# 建立 BasicSolution 作為保守版?
    • C-Q2: 如何撰寫 MSTest 單元測試比對兩版本?
  • 中級者:建議學習哪 20 題
    • A-Q6: 什麼是動態測試案例產生(自動化測資)?
    • A-Q13: 在演算法學習中先寫保守版的核心價值是什麼?
    • A-Q14: 什麼是執行期驗證(Runtime Verification)?
    • B-Q4: 兩版本比對的測試執行流程為何?
    • B-Q5: 如何設計「涵蓋率提升」的資料生成管線?
    • B-Q6: ZumaGame 的 AssertStatisticData 機制是什麼?
    • B-Q7: 在 ApplyStep 中插入斷言的流程是什麼?
    • B-Q8: Conditional Compilation(LOCAL_DEBUG)的技術架構?
    • B-Q9: Fail-Fast 在系統設計中如何落地?
    • B-Q10: 單元測試的黑箱與白箱界定為何?
    • B-Q12: 以保守版作為測試預言機的理論基礎是什麼?
    • B-Q13: 隨機測試(Fuzzing)的流程與風險控制?
    • B-Q15: ToString 對 Debugger 可視化的技術要點?
    • C-Q3: 如何實作 GenRandomText 產生動態測資?
    • C-Q4: 如何將動態測資轉成靜態 .csv/.xml 資料源?
    • C-Q5: 如何用條件式編譯加入除錯輔助且不影響提交?
    • C-Q6: 如何在演算法核心安插 Fail-Fast 檢查點?
    • C-Q7: 如何覆寫 ToString 以利調試與記錄?
    • D-Q1: 兩版本結果不一致怎麼辦?
    • D-Q2: 隨機測試偶發失敗如何診斷?
  • 高級者:建議關注哪 15 題
    • A-Q15: 在重構與微服務遷移中兩版本比對的重要性?
    • B-Q11: 微服務重構中的運行期鏡像比對架構是什麼?
    • B-Q14: 最佳化演算法的漸進替換與回歸保護機制?
    • C-Q8: 重構時如何進行執行期新舊版本 Side-by-side 比對?
    • C-Q9: 如何為 ZumaGame 維護統計一致性檢查?
    • C-Q10: 如何設計測試集以涵蓋極端與長度邊界?
    • D-Q3: 測試生成過慢影響研發節奏怎麼優化?
    • D-Q4: 在 LeetCode 提交遇到除錯碼影響效能怎麼辦?
    • D-Q5: 運行期斷言導致程式崩潰如何處置?
    • D-Q6: 統計資料與實際狀態不一致怎麼排查?
    • D-Q7: 單元測試不足導致回歸缺失怎麼補救?
    • D-Q8: 最佳化版效能未提升或變慢的原因?
    • D-Q9: Fuzz 測試產生重複或低質案例怎麼改善?
    • D-Q10: 重構跨服務引入行為變更如何追蹤?
    • B-Q5: 如何設計「涵蓋率提升」的資料生成管線?





Facebook Pages

AI Synthesis Contents

Edit Post (Pull Request)

Post Directory