自我測試程式碼

2014 年 5 月 1 日

自我測試程式碼是我在 重構 中用來指稱撰寫全面自動化測試並與功能性軟體結合的實務。如果執行得當,這將允許您呼叫執行測試的單一指令碼,而且您有信心這些測試會找出隱藏在程式碼中的任何錯誤。

我第一次在 OOPSLA 會議上聽見這個想法,當時 "Beddara" Dave Thomas 說每個物件都應該能夠自我測試。我突然想到輸入指令碼並讓整個軟體系統進行自我測試的畫面,很像開機時看到的硬體記憶體測試。不久後,我就在自己的專案中探索這種方法,並對其好處感到非常滿意。幾年後,我與 Kent Beck 合作,發現他也在做同樣的事情,但他的方式比我複雜許多。這是在 Kent(和 Erich Gamma)製作 JUnit 不久之前,JUnit 成為許多自我測試程式碼(及其姊妹:TestDrivenDevelopment)思考和實務的基礎。

當你能夠對程式碼庫執行一系列自動化測試,並確信如果測試通過,你的程式碼就沒有任何重大缺陷時,你就有自測試程式碼。我認為的一種方式是,除了建構你的軟體系統之外,你同時建構一個錯誤偵測器,它能夠偵測系統內的任何錯誤。如果團隊中的任何人意外地引入了錯誤,偵測器就會啟動。透過頻繁執行測試套件,至少一天執行好幾次,你就能在錯誤引入後立即偵測到它們,因此你只要查看最近的變更,就能更容易找到它們。沒有工作程式碼和測試來維持它的運作,程式設計的過程就不完整。我們的態度是假設任何沒有測試的非平凡程式碼都是有問題的。

自測試程式碼是持續整合的關鍵部分,我確實認為,除非你有自測試程式碼,否則你並未真正執行持續整合。作為持續整合的支柱,它也是持續交付的必要部分。

自測試程式碼一個顯而易見的好處是,它可以大幅減少進入生產軟體的錯誤數量。其核心是建立一種測試文化,開發人員自然而然會想到同時撰寫程式碼和測試。

但最大的好處不只是避免生產錯誤,而是你對系統進行變更的信心。舊程式碼庫通常是令人害怕的地方,開發人員害怕變更工作程式碼。甚至修正錯誤也可能很危險,因為你可能會製造出比你修正的錯誤更多的錯誤。在這種情況下,不僅新增更多功能非常緩慢,你還會害怕重構系統,從而增加技術負債,並陷入每一個變更都讓人們更害怕更多變更的惡性循環。

有了自測試程式碼,情況就不同了。在這種情況下,人們有信心可以安全地修正小問題來清理程式碼,因為如果你犯了錯誤(或更確切地說「當我犯了錯誤」),錯誤偵測器就會啟動,你可以快速復原並繼續。有了這個安全網,你就可以花時間保持程式碼處於良好狀態,並最終進入一個良性循環,在這個循環中,你新增新功能的速度會越來越快。

這些好處通常與測試驅動開發(TDD)有關,但將 TDD 和自測試程式碼的概念分開是有用的。我認為 TDD 是一種特定實務,其好處包括產生自測試程式碼。這是一個很棒的方法,而 TDD 是我非常喜歡的一種技術。但是你也可以在撰寫程式碼後撰寫測試來產生自測試程式碼,儘管在擁有測試(並且通過測試)之前,你不能認為你的工作已經完成了。自測試程式碼的重要點是你擁有測試,而不是你如何獲得它們。

實踐自測試程式碼的團隊,其一項重要的行為就是對生產錯誤的反應。使用自測試程式碼的團隊的常見反應是,先撰寫一個測試來揭露錯誤,然後才嘗試修復它。通常,撰寫這個測試可能實際上是一系列測試,逐漸縮小範圍,直到您到達一個觸發錯誤的單元測試。這是一個有用的除錯技巧,對於確保錯誤修復後保持修復狀態也很重要。通常,團隊也會使用這個錯誤作為靈感,尋找類似的遺漏測試。態度應該是,任何錯誤不只是程式碼的失敗,它同樣也是測試螢幕的失敗。

最近,我們看到自測試的另一個面向,更強調生產中的監控。持續交付讓您可以快速將軟體的新版本部署到生產環境中。在這種情況下,團隊投入更多精力來找出生產中的錯誤,並透過部署新的修正版本或回滾到最後已知的良好版本來快速修復它們。

此條目最初於 2005 年 5 月 5 日(以更小的形式)發布。