這個主題有 工程技藝書單其他三篇——設計判斷標準、系統架構、改既有的程式——都沒有的特徵:收錄的書彼此不同意。測試該寫到什麼粒度、協作對象該不該用 mock 替換、測試該綁在行為上還是結構上——這些問題有兩個互相對立的傳統,而多數讀者是在讀到第二本、發現它跟第一本說法相反的時候,才知道自己一直在照著其中一派做而不知道有另一派。

先拿哪一本,看現在卡在哪裡。還沒有立場、想知道這整件事在吵什麼,從 Beck 那本 開始——分歧的起點是他定的,後面幾本都在跟他對話。手上已經有一套測試而它正在造成負擔,跳過立場之爭直接拿 Khorikov 那本,那本是拿來逐項打分的。兩種都不是、只想要一套把規格變成測試案例的程序,Aniche 那本 的前置要求最低。不確定自己落在哪一格,就從 Beck 那本 開始——它是這一篇裡不需要先盤點自己就讀得動的那一本。

兩種定義的分野本身,在 Sociable vs Solitary Unit Test 那張卡。要診斷手上這套測試的邊界畫錯了沒有,讀 TDD 的兩種做法——那篇回答「所以我們怎麼做」,本篇回答「該讀哪本、每本代表什麼位置」。

起點書:Kent Beck 的 Test-Driven Development: By Example

這本是 TDD 的原始定義,2003 年出版,做的事情很單純:從頭到尾走完兩個小專案,把紅燈、綠燈、重構這個循環示範幾十次。讀它的價值不在學到技巧,在於看清楚那個循環的節奏究竟有多小——書中的步伐比多數人想像的細,細到會讓第一次讀的人覺得沒必要。

它是起點的理由是 Freeman 與 Pryce 那本、Khorikov 那本都在跟它對話。分歧從一個定義開始:測試的單元是什麼。Beck 的用法把單元當成一組協同工作的類別,測試對外的行為;後來的另一派——書市慣稱倫敦學派——把單元縮到單一類別,把所有協作者換成 mock。兩派的所有差異都從這個定義分岔出去。

證據來源是單一路徑的個人經驗,形式是作者逐步演練自己的實踐而非論證。時效上,範例是 Java 與 Python 的舊版本,測試框架也隔了兩個世代;紅綠重構的節奏與「讓測試驅動設計」這個主張不依賴那些。

處境相容性上,這套節奏預設提交的粒度由寫的人自己決定。流程若要求每個提交對應一張工單、或測試必須跟功能在同一個 PR 送審,書中那個細到讓人覺得沒必要的步伐就落不了地,要先改流程、或改用較粗的循環。

這本書幾乎不需要前置作業,但它預設讀者寫過測試——完全沒寫過的人會看不出那些步驟在避免什麼;先在自己的專案寫過幾個測試再來讀,那些步驟的用意才看得出來。繁體中文版《Kent Beck 的測試驅動開發:案例導向的逐步解決之道》,博碩出版、陳仕傑譯。

這幾本書的分歧所在

TDD 的原始定義出自 Kent Beck 的《Test-Driven Development: By Example》:怎麼從一個失敗的測試開始建立單元測試、怎麼用紅燈—綠燈—重構的小循環讓設計從小長到大。Freeman 與 Pryce 的《Growing Object-Oriented Software, Guided by Tests》在測試該怎麼設計上走了跟 Beck 不同的邏輯:由外而內開發,於是每遇到一個還不存在的協作對象就先用 mock 頂替。兩邊分岔的地方是同一個定義——測試的單元是什麼:Beck 把單元當成一組協同工作的類別,Freeman 與 Pryce 那一派(書市慣稱倫敦學派)把單元縮到單一類別。

無論選擇哪一種做法,測試寫完之後都要評估同一個問題,這套測試到底有沒有問題?Khorikov 的《Unit Testing Principles, Practices, and Patterns》就是提供這個評估的標準,這個標準無論對哪一派都適用。這本書中對於倫敦學派的批判也是基於這個系統。而判斷標準寫下來、交給機器或 agent 執行的時候,Bach 與 Bolton 的《Taking Testing Seriously》提出了一個討論,怎麼評估「執行事先寫好的判斷標準」與「設計判斷標準、發現沒人想到要問的問題」這兩種活動?這是 Beck、Freeman 與 Pryce、Khorikov 三本理論書都在討論的共同問題。釐清測試的方向之後,實務上還會需要討論單元的大小——三本理論書在這一題沒有取得共識,《Taking Testing Seriously》給出解法——以及怎麼從規格推導到測試案例(Aniche 的《Effective Software Testing》)。

Growing Object-Oriented Software, Guided by Tests:想看 mock 那一派的完整主張時的選讀

Steve Freeman 與 Nat Pryce 這本是倫敦學派的代表作,也是它最完整的一次陳述。主張是由外而內開發:從最外層的驗收測試開始,往內每遇到一個還不存在的協作對象就先用 mock 頂替,於是 mock 不只是測試工具,而是用來發現物件之間該有什麼關係的設計手段。

這個定位常被誤解。多數人把 mock 當成「真實依賴太慢所以換掉」,而這本書的主張是相反的——mock 是在那個依賴還不知道長什麼樣的時候,用寫測試的方式把它的介面逼出來。書中貫穿全書的那個範例完整走過一次這個流程,是它跟只講技巧的測試書的差別。

它也是這個主題裡爭議最集中的一本。批評集中在同一點:這種寫法讓測試綁在物件的協作結構上,於是重構內部結構時測試會大量壞掉,而重構本來不該破壞測試。這個批評成不成立,取決於單元怎麼定義——那正是 Khorikov 那本要處理的問題。

證據來源是單一路徑的個人經驗(兩位作者十年的系統開發),形式是主張加上一個長篇範例。時效上,範例是 Java 與 JMock,那部分已經很遠;由外而內的流程與 mock 當設計手段這個主張不依賴語言。

讀這本要先有一次自己造成的後果:寫過一套後來覺得難維護的測試。還沒有那個經驗時,這本的主張跟批評它的主張聽起來都有道理,讀的人沒有判斷的依據——它因此適合排在自己的測試開始出現維護負擔之後,而不是照出版順序讀。查不到中譯本。

Unit Testing Principles, Practices, and Patterns:要一組可以拿來評分的判斷標準時的選讀

Vladimir Khorikov 這本(2020)是討論單元定義的這幾本書裡最後出版的一本,也是唯一給出一套可以拿來評測試的通用判斷標準的一本。四支柱是防止回歸、抵抗重構、快速回饋、易於維護,而書中的核心論證是前三者互相衝突、不可能同時最大化,所以測試設計是取捨而非最佳實踐。這套判斷標準有一類測試評不了:為了替沒有測試的程式碼建立行為快照而寫、用完就丟的那種(改既有程式的選讀書目 收的 Feathers 那本教的手法),它在抵抗重構與易於維護上必然低分,而那正是它該有的樣子。四支柱預設被評的測試要長期留著。

它對倫敦學派的批評就建立在這組判斷標準上:把所有協作者 mock 掉會讓測試耦合到實作結構,因而在「抵抗重構」這一項上得分很低——而那一項是四支柱裡唯一不能用其他項補償的,因為一個會誤報的測試套件最終會被團隊忽略。作者主張的是古典學派:單元是行為而非類別,只有跨越應用邊界的協作對象(資料庫、外部服務)才該替換。

這本的用法跟 Beck、Freeman 與 Pryce 那兩本不同:它是拿來當標準的,而不是拿來讀完的。手上有一套自己覺得不對勁的測試時,逐項打分數比讀任何主張都快看出問題在哪。

證據來源是單一路徑的個人經驗加上理論建構,形式是原則加判斷標準——這是本篇收錄的書裡唯一嘗試把測試設計寫成可推導體系的。範例是 C#,但判斷標準本身與語言無關。時效上沒有明顯過時的部分——四支柱的取捨與工具世代無關。

這本要有量測的對象:手上一套實際在跑、而且開始造成負擔的測試。沒有那套測試,四支柱之間的取捨不會浮現——它們互相衝突,而衝突要有一套實際的測試當標的才看得見。還沒有這樣一套測試的話,可以先知道這本存在,等負擔出現再拿出來用。查不到繁體中文版,簡體中文版《單元測試:原則、實踐與模式》。

Taking Testing Seriously:想知道機器接手判斷標準之後人還做什麼時的選讀

James Bach 與 Michael Bolton 這本(Wiley,2025 年 11 月)是 Rapid Software Testing 這一派的完整陳述。它跟爭單元邊界的那三本理論書——Beck、Freeman 與 Pryce、Khorikov——不在同一個座標系裡:那三本爭的是邊界該畫在哪,這本主張要先分開的是兩種活動——checking(對一個已經被決定的事實做二元評估,判斷標準事先寫下、原則上可以交給機器)與 testing(設計判斷標準本身、發現沒有人想到要問的問題、判斷觀察到的現象算不算問題)。三本理論書給判斷標準的時候,同時在做這兩件事,只是沒有把它們分開命名。作者的立場是自動化能接手的只有 checking,而 checking 的品質完全取決於當初設計它的那次 testing。對單元該多大——三本理論書沒有取得共識的那一題——它的解法是把問題排到後面:先分開兩種活動,單元的大小是分界確立之後才輪到的問題。

這個分界是這一派的起點,理由是自動化的邊界由判斷標準寫不寫得下來決定,與工具能力無關。判斷標準交給 agent 執行之後人還剩下什麼工作,答案就從這條分界推出來。

證據來源是兩位作者長期的教學與顧問實踐加上一套自建的術語體系,形式是主張與啟發式的目錄而不是逐步演練——它不像 Freeman 與 Pryce 那本有一個貫穿全書的範例可以跟著做。時效上是本篇最新的一本,術語體系本身不依賴任何工具世代。

處境相容性上要先知道一件事:這一派的語彙(checking、oracle、heuristic、探索式測試的活動記錄)與多數團隊日常使用的詞彙不重疊,讀的時候要一邊做術語對照。它也預設讀者有機會親自操作產品——判斷標準要在觀察當下才成形是這套主張的核心,而完全只寫單元測試、不碰成品的人拿不到那個觀察位置。查不到中譯本。

Effective Software Testing:要一套推出測試案例的程序時的選讀

Maurício Aniche 這本(Manning,2022)處理的是四本立場書都沒有給的一項:這些測試案例是怎麼被推出來的。Khorikov 給的是評分用的標準,Beck 給的是循環的節奏,這本給的是從需求推導案例的步驟——先從規格切出等價類與邊界,再用覆蓋準則檢查有沒有漏掉分支,接著設計方法與類別的契約(前置條件、後置條件、不變量),最後回頭問這段程式碼的可測試性是不是設計本身的問題。

它跟提供標準的書搭配起來沒有重疊:標準回答「手上這套測試好不好」,這本回答「還缺哪幾個案例」。手上一套測試被評為分數低而不知道要補什麼時,缺的通常是這本教的推導程序。

證據來源是學術訓練加業界實踐(作者當時同時任教於 Delft 理工大學並在業界帶技術培訓),形式是步驟加練習,每章有可自己動手的題目。範例是 Java 與 JUnit,推導程序本身與語言無關。時效上沒有明顯過時的部分。

前置經驗要求比四本立場書低——它不預設讀者已經寫過一套難維護的測試,也不預設讀者對兩派分歧有立場。缺點的另一面是它不處理立場問題:讀完之後仍然要自己決定單元畫在哪,那要回到四本立場書。作者另有一套與本書同主題的免費線上課(見 公開課以外的影音路徑與檢索關鍵字),內容重疊但形式互補。查不到繁體中文版,另有簡體中文譯本。

測試各書的分工與沒收錄的框架手冊、規則推廣書

四本立場書彼此不同意,而它們的分歧點正是這個主題最難自己判斷的那一個。讀完會發現自己原本以為的「測試最佳實踐」是某一派的立場,而那個發現比任何單一技巧有用。Aniche 那本收在旁邊,補的是四本立場書都沒給的那一段:案例怎麼從規格推出來。

測試的書市有兩大類不在這裡。一類是特定框架的操作手冊,那類的時效跟框架版本綁死,且屬於教學系列的範圍。另一類是把測試金字塔或某個覆蓋率目標推銷成普適規則的書——它們的問題是規則脫離了推導它的取捨,而本篇收的書恰好證明那些取捨還在爭論中。

幾本常被一起提起的書落在別的軸上。Roy Osherove 的《單元測試的藝術》與 Gerard Meszaros 的《xUnit Test Patterns》是操作手冊與模式目錄,回答的是怎麼寫、有哪些形態,而不是哪一派主張什麼。Mark Winteringham 的《Software Testing with Generative AI》(Manning,2024)處理用生成式工具做測試,同屬工具操作層,時效跟工具版本綁死;要找那類內容的人它是現成的入口。

公開課以外的影音路徑與檢索關鍵字

以「軟體測試」為關鍵字找到的公開課集中在怎麼當一個測試工程師——測試種類的名詞、工具操作、面試會問什麼,那類內容預設有標準答案可以教。本篇要交付的是幾本書彼此不同意在哪,是一組還在爭論中的立場,兩者不在同一層。

但這不表示這個主題沒有影音路徑,它出現在別的關鍵字底下。問「分歧在哪」的影音內容出現在 TDD、software engineering、craftsmanship 這幾個關鍵字下,而不在 software testing 下——後者的檢索結果被測試工程師的職涯內容佔滿。讀不動長篇文字的讀者要換的是關鍵字,不是放棄。

供給的形態依製作者的商業模式分成三種,判斷免費內容拿得到多少要先看這個:

形態免費內容的位置這個主題拿得到什麼
內容型(付費課程靠免費內容引流)影音平台頻道,量大且完整Dave Farley 的 Continuous Delivery 與 Modern Software Engineering 頻道、Emily Bache 的頻道(approval testing 與重構的逐步演練)、Khorikov 的 Enterprise Craftsmanship 部落格
顧問型(課程面向企業、不靠影音引流)長篇文字,不是影音Bach 與 Bolton 的 developsense.com 與 satisfice.com;想改看影音、不讀長文的人,在這一派找不到影音內容
平台型(全免費、靠上游產品變現)課程平台本身工具操作為主(Selenium、Cypress、Playwright、Appium),填不了立場分歧那個缺口

學術機構開的免費課最貼近本篇主題:Delft 理工大學在 edX 上的 Automated Software Testing 系列由 Aniche 與 Arie van Deursen 開設,內容是單元測試、覆蓋準則與可測試性設計,與上面收錄的《Effective Software Testing》同源而形式互補。

工程技藝書單整體的公開課供給狀況寫在 工程技藝書單的公開課段。

測試的相鄰主題與接續閱讀

測試寫不出來常常是設計的訊號而非測試技巧的問題——難測的程式碼通常是耦合太緊。設計判斷的選書收在 設計判斷標準與日常實踐的選讀書目。既有程式碼沒有測試而必須先補,那是 改既有程式的選讀書目 裡 Feathers 那本處理的問題。

站內自己的測試分層策略、協議整合驗證與實機教訓看 Testing 測試策略;測試邊界畫錯時看得出來的症狀、以及本站多數內容為什麼落在古典派那一側(含那個選擇本身帶著什麼立場),在 TDD 的兩種做法。

程式碼由 agent 產出、而人不打算逐行讀時,判斷標準該放在哪裡,討論收在 模組六:Agent 產出程式碼的驗證——那裡處理的是本篇四本立場書共同預設而在那個情境下失效的前提:測試由懂需求的人寫,而那個人會讀自己的程式碼。Bach 與 Bolton 那本的 checking 與 testing 分界是這條路線的上游概念。