「99% 的失敗,來自那些習慣找藉口的人。」——發明家暨植物學家喬治・華盛頓・卡佛(George Washington Carver)

頭號測試工具是人腦#

頭號測試工具不是電腦,而是人腦——連同眼、耳與其他感官。再多的運算力也無法彌補「不動腦的測試」,但充沛的腦力能彌補一台缺席或不可用的電腦。

正因如此,巴赫(James Bach)主張用「智性測試(sapient testing)」取代「手動測試(manual testing)」一詞。他形容:「『手動測試』讓人聯想到鏈鎖囚犯在搬石頭,你會立刻納悶他們為何不乾脆用挖土機。」

純靠機器測試永遠不夠#

把大量腦力投入測試最簡單的方式,就是技術審查(technical review)——同儕坐下來作為一個團隊,分析並記錄某技術產物(程式碼、設計、規格、使用手冊)的優劣。

  • 對程式碼而言,這不是把產品當「黑箱」,而是「白箱/透明箱/開箱」測試
  • 雖然沒人敲鍵盤,這確實是測試:「蒐集產品相關資訊,意圖讓資訊能用於某目的」
  • 技術審查的明顯優勢是能用於「機器難以測試」的材料(你怎麼用電腦測一份可行性研究?)

機器測試與技術審查不是二選一。兩者結合特別強大,因為它們傾向找到「不同類型」的 bug:單用其中一種、做得好,對程式碼約能找到 60–70% 的 bug;結合起來常能找到 90% 以上。

即時審查(Instant Reviews)#

關於技術審查最常見的抱怨是「太花時間」。缺乏審查經驗的組織之所以這麼想,常是因為他們不知道審查何時算完成——很多情況下,審查甚至在這些新手意識到「它開始了」之前就已結束。

作者把這種「當有人給出一個理由說某產物不能或不該被審查」時發生的審查稱為即時審查。這些「理由」本身就是生產者思考過程中的 bug(而非產品的 bug),而每一條理由都已構成一次即時審查。

以下是常見的「擋審查」理由與其即時審查結論:

  • 「審查這產品太花時間」→ 議題在於產品大小不當,必須拆成可審查(即可理解)的小塊
  • 「但產品無法拆成可審查的小塊」→ 它是一大團無法理解的東西,建議重做成可審查的形式;若大到不能審查,肯定也大到無法用其他方式測試
  • 「只有作者本人看得懂這段程式碼」→ 必須重建成可使用、可維護的形式,除非你願意在產品的整個生命週期都附送作者
  • 「這顯而易見」→ 若真顯而易見,審查只需幾秒,何必反對?作者半世紀來從沒見過真正符合此宣稱的軟體
  • 「太小了,不值得,能出什麼錯?」→ 若這麼小,審查能又快又省地告訴你能出什麼錯。別忘了「一行程式碼的改動」害組織損失十億美元、甚至害死人的案例
  • 「太晚了」→ 也許確實太晚改產品,但這代表開發流程本身有問題
  • 「太早了」→ 若排程說某物該準備好接受審查卻沒準備好,議題就是你進度落後了
  • 「是時候審查了,但我還在修 bug」→ 產品很多 bug 時更該立刻審查以幫助陷入麻煩的開發者;沒有開發者好到能持續獨力把事情做對
  • 「我們不知道它該解決什麼問題」→ 那你到底為何要做它?某份上游文件或流程沒完成或沒被理解;若根本沒有要解的問題,結論就是「丟掉,別再浪費錢」
  • 「我們邊做邊定義問題」→ 自稱用敏捷流程的客戶常這麼說,但他們誤解了敏捷:應逐一審查每個「故事(story)」、設計驗收測試、審查,再測試成果,如此漸進到客戶說沒有更多故事為止
  • 「我們得花好幾週準備審查」→ 若需要好幾週準備,代表他們根本沒產出該被測試/審查的交付物,那產品依定義就尚未完成
  • 「我們不想讓人看我們在做什麼,因為我們的人太敏感」→ 不是用錯了人,就是管理不當(或他們打算用程式偷東西、或勒索你)
  • 「無法審查效能,因為要做出來才知道,到時再優化」→ 何必賭運氣?該問「這看起來有機會表現得當嗎?」若肯定,再問「它寫得讓未來的優化者看得懂嗎?」
  • 「我們 builder 內部審過了,再審是浪費時間」→ 若做得好,第二次審查很快,還能確保 builder 以外的人也看得懂;若內部審得不好,產品大概也做得不好
  • 「我們之前審過類似的東西」→ 太好了,那這次能更迅速,還能比較兩次結果取得額外資訊
  • 「你和審查者在這領域不夠格,唯一夠格的人都在這專案上」→ 若專案外真的沒有夠格的審查者,這產品保證會是無止境的維護問題,並有重大資安漏洞
  • 「沒什麼新東西,全是可重用程式碼」→ 太好了,那審查會又短又甜——前提是我們有每塊可重用元件及其介面狀態的文件證據
  • 「只要照指示做,絕不會出錯」→ 通常代表 builder 不知道使用者「不照指示」時會發生什麼
  • 「我們〔測過〕〔試過〕〔展示過〕,沒問題(okay)」→ 議題在於「okay」的定義,那是英語中最模糊的催眠詞之一
  • 「它能運作(it works)」→「它(it)」和「運作(works)」是另兩個最模糊的詞,通常意味著「我們沒太努力讓它失敗,也沒跑很久或在多樣條件下跑」
  • 「我們從沒遇過困難」→ 很好,現在來看看非 builder 是否同樣幸運,你預測呢?
  • 「我們不知道它爛到需要審查」→ 別把審查當成對「你認為很爛的工作」的懲罰;審查該是標準、普世的流程
  • 「我們不知道需要審查它」→ 那你不懂自己的開發流程,解法是教育與溝通
  • 「我們落後了,但希望走運趕上」→ 給管理層的完整審查報告可以很精簡:「他們在指望走運。」希望你的管理層知道軟體開發不靠運氣
  • 「我們覺得自己做得不好,不想讓管理層發現」→ 你當然不會聽到有人明說,但這是許多即時審查偵測到的;有趣的是,審查通常顯示這些產物沒 builder 怕的那麼糟,卻也沒他們希望的那麼好
  • 「我們不想配合那些流程納粹」→ 很少被說出口,卻可能是其他藉口背後更深的原因:感到被使喚而非被尊重。此時該做一次「後設審查」——審查你的審查系統,找出「拿審查當懲罰」「把技術審查偷渡成人事考核」等流程 bug

最糟優先(Worst-First)確立 bug 嚴重度#

進到審查室後,最快的審查以「最糟優先」進行:請每位審查者從他找到的最糟問題開始,往下處理到相對次要的。若程式用了有缺陷的演算法,就沒必要操心介面的拼字錯誤。

審查是一種測試。從測試角度看最糟的 bug,是那些「阻擋測試」的 bug。若審查者說「我看不懂這段程式碼、無法確定它能運作」,這就是阻擋議題,因此具最高重要性。

遇到這類阻擋性說法卻不知如何是好時,把異議翻譯成測試術語。例如「客戶不想付費所以無法審查產品」變成「客戶不想付費所以無法測試產品」——你立刻就知道該怎麼辦(雖然客戶未必知道,那麼就有人得負責把後果講清楚)。

真相未必有說服力#

即時審查以極小的時間投入,換來大量重要且及早的資訊。但要警覺:即時審查能說服「你」,你卻仍得花力氣說服「別人」——他們很難相信,別人能用如此簡單的方式,對他們投入這麼多心血的東西學到這麼多。

有時你得走完一次完整審查讓 builder 親眼看見結論如何產生;有時你得開始測試、讓早期結果揭露本該在審查中發現的問題。漸漸地,組織會學會自己做即時審查。

測試人員是有價值的審查者#

管理者常說「測試人員不寫程式,找不到 bug,不必參加技術審查」。作者反駁:「這根本不對。你不需要懂任何程式語言,就能找出邏輯 bug、重大設計缺陷、糟糕的人機介面、規格歧義等諸多問題。」

即使測試人員真的找不到 bug(其實會找到),他們仍能從中學習——而學習正是審查最大的單一好處

  1. 觀察開發者常見的錯誤思考模式,學會編寫更好的測試
  2. 及早審查規格,搶先掌握測試計畫的範圍
  3. 熟悉設計,加速偵測 bug 並協助釘定
  4. 透過參與審查,學會更好地審查自己的測試案例、計畫、驅動程式與工具,並能比「乾等開發者給東西測」的測試人員更快進入狀況

小結#

不靠電腦的測試方法有很多,但沒有任何測試方法是「不需動腦」的。及早且頻繁地測試,動用你能召集的所有腦力。

常見錯誤#

以下是輕忽「不靠機器測試」時最常見的失誤。

  1. 不認可技術審查作為互補測試形式的價值:沒有納入定期技術審查的流程,無論機器測試多好,專案都無法擺脫平庸
  2. 被各種「跳過技術審查(或任何流程步驟)」的論點說服:任何系統中,約十之八九的問題多、易出錯元件,都繞過或抄了某些流程步驟
  3. 拿技術審查當懲罰:要培養讓每次審查都成為所有參與者收穫的氛圍
  4. 為省時間而跳過審查:錯誤是專案時間流失的頭號原因,跳過審查總會讓專案更久
  5. 不為「可測試性」審查設計與程式碼:只要系統設計時就考慮可測試性,至少一半的測試成本能在任何測試開跑前就砍掉
  6. 不把測試人員納為審查者:他們貢獻獨特觀點,也需要每次審查帶來的教育
  7. 不認可學習的價值:學習終究是審查最有價值的部分——你或許因它難以量化而沒把它算進來,但只要你真想,它是可以量化的